From d42b70325a400a1c496ae44183ca7f4aca1261d2 Mon Sep 17 00:00:00 2001 From: Todd Sales Date: Mon, 23 Jun 2025 21:01:55 -0400 Subject: [PATCH] Initial commit --- Buff.xlsx | Bin 0 -> 34373 bytes check_db.py | 43 + my_project_data.db | Bin 0 -> 61440 bytes .../asgiref-3.8.1.dist-info/INSTALLER | 1 + .../asgiref-3.8.1.dist-info/LICENSE | 27 + .../asgiref-3.8.1.dist-info/METADATA | 246 + .../asgiref-3.8.1.dist-info/RECORD | 27 + .../asgiref-3.8.1.dist-info/WHEEL | 5 + .../asgiref-3.8.1.dist-info/top_level.txt | 1 + venv/Lib/site-packages/asgiref/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 213 bytes .../__pycache__/compatibility.cpython-312.pyc | Bin 0 -> 1797 bytes .../current_thread_executor.cpython-312.pyc | Bin 0 -> 4986 bytes .../asgiref/__pycache__/local.cpython-312.pyc | Bin 0 -> 5813 bytes .../__pycache__/server.cpython-312.pyc | Bin 0 -> 7956 bytes .../asgiref/__pycache__/sync.cpython-312.pyc | Bin 0 -> 22926 bytes .../__pycache__/testing.cpython-312.pyc | Bin 0 -> 6070 bytes .../__pycache__/timeout.cpython-312.pyc | Bin 0 -> 4896 bytes .../__pycache__/typing.cpython-312.pyc | Bin 0 -> 9910 bytes .../asgiref/__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 7300 bytes .../site-packages/asgiref/compatibility.py | 48 + .../asgiref/current_thread_executor.py | 115 + venv/Lib/site-packages/asgiref/local.py | 128 + venv/Lib/site-packages/asgiref/py.typed | 0 venv/Lib/site-packages/asgiref/server.py | 157 + venv/Lib/site-packages/asgiref/sync.py | 613 ++ venv/Lib/site-packages/asgiref/testing.py | 103 + venv/Lib/site-packages/asgiref/timeout.py | 118 + venv/Lib/site-packages/asgiref/typing.py | 278 + venv/Lib/site-packages/asgiref/wsgi.py | 166 + .../et_xmlfile-2.0.0.dist-info/AUTHORS.txt | 5 + .../et_xmlfile-2.0.0.dist-info/INSTALLER | 1 + .../et_xmlfile-2.0.0.dist-info/LICENCE.python | 298 + .../et_xmlfile-2.0.0.dist-info/LICENCE.rst | 23 + .../et_xmlfile-2.0.0.dist-info/METADATA | 51 + .../et_xmlfile-2.0.0.dist-info/RECORD | 14 + .../et_xmlfile-2.0.0.dist-info/WHEEL | 5 + .../et_xmlfile-2.0.0.dist-info/top_level.txt | 1 + venv/Lib/site-packages/et_xmlfile/__init__.py | 8 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 447 bytes .../incremental_tree.cpython-312.pyc | Bin 0 -> 24461 bytes .../__pycache__/xmlfile.cpython-312.pyc | Bin 0 -> 5484 bytes .../et_xmlfile/incremental_tree.py | 917 ++ venv/Lib/site-packages/et_xmlfile/xmlfile.py | 158 + .../openpyxl-3.1.5.dist-info/INSTALLER | 1 + .../openpyxl-3.1.5.dist-info/LICENCE.rst | 23 + .../openpyxl-3.1.5.dist-info/METADATA | 86 + .../openpyxl-3.1.5.dist-info/RECORD | 387 + .../openpyxl-3.1.5.dist-info/REQUESTED | 0 .../openpyxl-3.1.5.dist-info/WHEEL | 6 + .../openpyxl-3.1.5.dist-info/top_level.txt | 1 + venv/Lib/site-packages/openpyxl/__init__.py | 19 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 818 bytes .../__pycache__/_constants.cpython-312.pyc | Bin 0 -> 522 bytes venv/Lib/site-packages/openpyxl/_constants.py | 13 + .../site-packages/openpyxl/cell/__init__.py | 4 + .../cell/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 326 bytes .../cell/__pycache__/_writer.cpython-312.pyc | Bin 0 -> 5410 bytes .../cell/__pycache__/cell.cpython-312.pyc | Bin 0 -> 12345 bytes .../__pycache__/read_only.cpython-312.pyc | Bin 0 -> 6584 bytes .../__pycache__/rich_text.cpython-312.pyc | Bin 0 -> 9303 bytes .../cell/__pycache__/text.cpython-312.pyc | Bin 0 -> 5559 bytes .../site-packages/openpyxl/cell/_writer.py | 136 + venv/Lib/site-packages/openpyxl/cell/cell.py | 332 + .../site-packages/openpyxl/cell/read_only.py | 136 + .../site-packages/openpyxl/cell/rich_text.py | 202 + venv/Lib/site-packages/openpyxl/cell/text.py | 184 + venv/Lib/site-packages/openpyxl/chart/_3d.py | 105 + .../site-packages/openpyxl/chart/__init__.py | 19 + .../chart/__pycache__/_3d.cpython-312.pyc | Bin 0 -> 3440 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 896 bytes .../chart/__pycache__/_chart.cpython-312.pyc | Bin 0 -> 8515 bytes .../__pycache__/area_chart.cpython-312.pyc | Bin 0 -> 3911 bytes .../chart/__pycache__/axis.cpython-312.pyc | Bin 0 -> 13344 bytes .../__pycache__/bar_chart.cpython-312.pyc | Bin 0 -> 5003 bytes .../__pycache__/bubble_chart.cpython-312.pyc | Bin 0 -> 2380 bytes .../__pycache__/chartspace.cpython-312.pyc | Bin 0 -> 6008 bytes .../__pycache__/data_source.cpython-312.pyc | Bin 0 -> 7827 bytes .../__pycache__/descriptors.cpython-312.pyc | Bin 0 -> 1429 bytes .../__pycache__/error_bar.cpython-312.pyc | Bin 0 -> 2110 bytes .../chart/__pycache__/label.cpython-312.pyc | Bin 0 -> 4529 bytes .../chart/__pycache__/layout.cpython-312.pyc | Bin 0 -> 2372 bytes .../chart/__pycache__/legend.cpython-312.pyc | Bin 0 -> 2432 bytes .../__pycache__/line_chart.cpython-312.pyc | Bin 0 -> 4555 bytes .../chart/__pycache__/marker.cpython-312.pyc | Bin 0 -> 2751 bytes .../chart/__pycache__/picture.cpython-312.pyc | Bin 0 -> 1295 bytes .../__pycache__/pie_chart.cpython-312.pyc | Bin 0 -> 6056 bytes .../chart/__pycache__/pivot.cpython-312.pyc | Bin 0 -> 2215 bytes .../__pycache__/plotarea.cpython-312.pyc | Bin 0 -> 6421 bytes .../print_settings.cpython-312.pyc | Bin 0 -> 2129 bytes .../__pycache__/radar_chart.cpython-312.pyc | Bin 0 -> 2032 bytes .../chart/__pycache__/reader.cpython-312.pyc | Bin 0 -> 1795 bytes .../__pycache__/reference.cpython-312.pyc | Bin 0 -> 4974 bytes .../__pycache__/scatter_chart.cpython-312.pyc | Bin 0 -> 2043 bytes .../chart/__pycache__/series.cpython-312.pyc | Bin 0 -> 5918 bytes .../series_factory.cpython-312.pyc | Bin 0 -> 1748 bytes .../chart/__pycache__/shapes.cpython-312.pyc | Bin 0 -> 2847 bytes .../__pycache__/stock_chart.cpython-312.pyc | Bin 0 -> 1975 bytes .../__pycache__/surface_chart.cpython-312.pyc | Bin 0 -> 4439 bytes .../chart/__pycache__/text.cpython-312.pyc | Bin 0 -> 2504 bytes .../chart/__pycache__/title.cpython-312.pyc | Bin 0 -> 2914 bytes .../__pycache__/trendline.cpython-312.pyc | Bin 0 -> 3135 bytes .../__pycache__/updown_bars.cpython-312.pyc | Bin 0 -> 1225 bytes .../site-packages/openpyxl/chart/_chart.py | 199 + .../openpyxl/chart/area_chart.py | 106 + venv/Lib/site-packages/openpyxl/chart/axis.py | 401 + .../site-packages/openpyxl/chart/bar_chart.py | 144 + .../openpyxl/chart/bubble_chart.py | 67 + .../openpyxl/chart/chartspace.py | 195 + .../openpyxl/chart/data_source.py | 246 + .../openpyxl/chart/descriptors.py | 43 + .../site-packages/openpyxl/chart/error_bar.py | 62 + .../Lib/site-packages/openpyxl/chart/label.py | 127 + .../site-packages/openpyxl/chart/layout.py | 74 + .../site-packages/openpyxl/chart/legend.py | 75 + .../openpyxl/chart/line_chart.py | 129 + .../site-packages/openpyxl/chart/marker.py | 90 + .../site-packages/openpyxl/chart/picture.py | 35 + .../site-packages/openpyxl/chart/pie_chart.py | 177 + .../Lib/site-packages/openpyxl/chart/pivot.py | 65 + .../site-packages/openpyxl/chart/plotarea.py | 162 + .../openpyxl/chart/print_settings.py | 57 + .../openpyxl/chart/radar_chart.py | 55 + .../site-packages/openpyxl/chart/reader.py | 32 + .../site-packages/openpyxl/chart/reference.py | 124 + .../openpyxl/chart/scatter_chart.py | 53 + .../site-packages/openpyxl/chart/series.py | 197 + .../openpyxl/chart/series_factory.py | 41 + .../site-packages/openpyxl/chart/shapes.py | 89 + .../openpyxl/chart/stock_chart.py | 54 + .../openpyxl/chart/surface_chart.py | 119 + venv/Lib/site-packages/openpyxl/chart/text.py | 78 + .../Lib/site-packages/openpyxl/chart/title.py | 76 + .../site-packages/openpyxl/chart/trendline.py | 98 + .../openpyxl/chart/updown_bars.py | 31 + .../openpyxl/chartsheet/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 249 bytes .../__pycache__/chartsheet.cpython-312.pyc | Bin 0 -> 4187 bytes .../__pycache__/custom.cpython-312.pyc | Bin 0 -> 2109 bytes .../__pycache__/properties.cpython-312.pyc | Bin 0 -> 1080 bytes .../__pycache__/protection.cpython-312.pyc | Bin 0 -> 1512 bytes .../__pycache__/publish.cpython-312.pyc | Bin 0 -> 1995 bytes .../__pycache__/relation.cpython-312.pyc | Bin 0 -> 3407 bytes .../__pycache__/views.cpython-312.pyc | Bin 0 -> 1775 bytes .../openpyxl/chartsheet/chartsheet.py | 107 + .../openpyxl/chartsheet/custom.py | 61 + .../openpyxl/chartsheet/properties.py | 28 + .../openpyxl/chartsheet/protection.py | 41 + .../openpyxl/chartsheet/publish.py | 58 + .../openpyxl/chartsheet/relation.py | 97 + .../openpyxl/chartsheet/views.py | 51 + .../openpyxl/comments/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/author.cpython-312.pyc | Bin 0 -> 815 bytes .../__pycache__/comment_sheet.cpython-312.pyc | Bin 0 -> 7233 bytes .../__pycache__/comments.cpython-312.pyc | Bin 0 -> 2897 bytes .../__pycache__/shape_writer.cpython-312.pyc | Bin 0 -> 4885 bytes .../site-packages/openpyxl/comments/author.py | 21 + .../openpyxl/comments/comment_sheet.py | 211 + .../openpyxl/comments/comments.py | 62 + .../openpyxl/comments/shape_writer.py | 112 + .../site-packages/openpyxl/compat/__init__.py | 54 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2168 bytes .../compat/__pycache__/abc.cpython-312.pyc | Bin 0 -> 375 bytes .../__pycache__/numbers.cpython-312.pyc | Bin 0 -> 1485 bytes .../__pycache__/product.cpython-312.pyc | Bin 0 -> 632 bytes .../__pycache__/singleton.cpython-312.pyc | Bin 0 -> 2039 bytes .../__pycache__/strings.cpython-312.pyc | Bin 0 -> 979 bytes venv/Lib/site-packages/openpyxl/compat/abc.py | 8 + .../site-packages/openpyxl/compat/numbers.py | 43 + .../site-packages/openpyxl/compat/product.py | 17 + .../openpyxl/compat/singleton.py | 40 + .../site-packages/openpyxl/compat/strings.py | 25 + .../openpyxl/descriptors/__init__.py | 58 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3136 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 13241 bytes .../__pycache__/container.cpython-312.pyc | Bin 0 -> 2072 bytes .../__pycache__/excel.cpython-312.pyc | Bin 0 -> 4286 bytes .../__pycache__/namespace.cpython-312.pyc | Bin 0 -> 505 bytes .../__pycache__/nested.cpython-312.pyc | Bin 0 -> 4682 bytes .../__pycache__/sequence.cpython-312.pyc | Bin 0 -> 6359 bytes .../__pycache__/serialisable.cpython-312.pyc | Bin 0 -> 9252 bytes .../__pycache__/slots.cpython-312.pyc | Bin 0 -> 1439 bytes .../openpyxl/descriptors/base.py | 272 + .../openpyxl/descriptors/container.py | 41 + .../openpyxl/descriptors/excel.py | 112 + .../openpyxl/descriptors/namespace.py | 12 + .../openpyxl/descriptors/nested.py | 129 + .../openpyxl/descriptors/sequence.py | 136 + .../openpyxl/descriptors/serialisable.py | 240 + .../openpyxl/descriptors/slots.py | 18 + .../openpyxl/drawing/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 240 bytes .../__pycache__/colors.cpython-312.pyc | Bin 0 -> 13197 bytes .../__pycache__/connector.cpython-312.pyc | Bin 0 -> 4937 bytes .../__pycache__/drawing.cpython-312.pyc | Bin 0 -> 3960 bytes .../__pycache__/effect.cpython-312.pyc | Bin 0 -> 13215 bytes .../drawing/__pycache__/fill.cpython-312.pyc | Bin 0 -> 12676 bytes .../__pycache__/geometry.cpython-312.pyc | Bin 0 -> 19889 bytes .../__pycache__/graphic.cpython-312.pyc | Bin 0 -> 5600 bytes .../drawing/__pycache__/image.cpython-312.pyc | Bin 0 -> 2604 bytes .../drawing/__pycache__/line.cpython-312.pyc | Bin 0 -> 4442 bytes .../__pycache__/picture.cpython-312.pyc | Bin 0 -> 4381 bytes .../__pycache__/properties.cpython-312.pyc | Bin 0 -> 5443 bytes .../__pycache__/relation.cpython-312.pyc | Bin 0 -> 798 bytes .../spreadsheet_drawing.cpython-312.pyc | Bin 0 -> 14797 bytes .../drawing/__pycache__/text.cpython-312.pyc | Bin 0 -> 21241 bytes .../drawing/__pycache__/xdr.cpython-312.pyc | Bin 0 -> 1358 bytes .../site-packages/openpyxl/drawing/colors.py | 435 + .../openpyxl/drawing/connector.py | 144 + .../site-packages/openpyxl/drawing/drawing.py | 92 + .../site-packages/openpyxl/drawing/effect.py | 407 + .../site-packages/openpyxl/drawing/fill.py | 425 + .../openpyxl/drawing/geometry.py | 584 ++ .../site-packages/openpyxl/drawing/graphic.py | 177 + .../site-packages/openpyxl/drawing/image.py | 65 + .../site-packages/openpyxl/drawing/line.py | 144 + .../site-packages/openpyxl/drawing/picture.py | 144 + .../openpyxl/drawing/properties.py | 174 + .../openpyxl/drawing/relation.py | 17 + .../openpyxl/drawing/spreadsheet_drawing.py | 382 + .../site-packages/openpyxl/drawing/text.py | 717 ++ .../Lib/site-packages/openpyxl/drawing/xdr.py | 33 + .../openpyxl/formatting/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 237 bytes .../__pycache__/formatting.cpython-312.pyc | Bin 0 -> 5115 bytes .../__pycache__/rule.cpython-312.pyc | Bin 0 -> 9642 bytes .../openpyxl/formatting/formatting.py | 114 + .../site-packages/openpyxl/formatting/rule.py | 291 + .../openpyxl/formula/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 244 bytes .../__pycache__/tokenizer.cpython-312.pyc | Bin 0 -> 20493 bytes .../__pycache__/translate.cpython-312.pyc | Bin 0 -> 7493 bytes .../openpyxl/formula/tokenizer.py | 446 + .../openpyxl/formula/translate.py | 166 + .../openpyxl/packaging/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 298 bytes .../__pycache__/core.cpython-312.pyc | Bin 0 -> 4250 bytes .../__pycache__/custom.cpython-312.pyc | Bin 0 -> 11313 bytes .../__pycache__/extended.cpython-312.pyc | Bin 0 -> 4467 bytes .../__pycache__/interface.cpython-312.pyc | Bin 0 -> 1754 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 0 -> 8255 bytes .../__pycache__/relationship.cpython-312.pyc | Bin 0 -> 6321 bytes .../__pycache__/workbook.cpython-312.pyc | Bin 0 -> 6593 bytes .../site-packages/openpyxl/packaging/core.py | 115 + .../openpyxl/packaging/custom.py | 289 + .../openpyxl/packaging/extended.py | 137 + .../openpyxl/packaging/interface.py | 56 + .../openpyxl/packaging/manifest.py | 194 + .../openpyxl/packaging/relationship.py | 158 + .../openpyxl/packaging/workbook.py | 185 + .../site-packages/openpyxl/pivot/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 194 bytes .../pivot/__pycache__/cache.cpython-312.pyc | Bin 0 -> 28679 bytes .../pivot/__pycache__/fields.cpython-312.pyc | Bin 0 -> 8178 bytes .../pivot/__pycache__/record.cpython-312.pyc | Bin 0 -> 3902 bytes .../pivot/__pycache__/table.cpython-312.pyc | Bin 0 -> 38478 bytes .../Lib/site-packages/openpyxl/pivot/cache.py | 965 ++ .../site-packages/openpyxl/pivot/fields.py | 326 + .../site-packages/openpyxl/pivot/record.py | 111 + .../Lib/site-packages/openpyxl/pivot/table.py | 1261 +++ .../site-packages/openpyxl/reader/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 195 bytes .../__pycache__/drawings.cpython-312.pyc | Bin 0 -> 3241 bytes .../reader/__pycache__/excel.cpython-312.pyc | Bin 0 -> 16861 bytes .../__pycache__/strings.cpython-312.pyc | Bin 0 -> 1717 bytes .../__pycache__/workbook.cpython-312.pyc | Bin 0 -> 6675 bytes .../site-packages/openpyxl/reader/drawings.py | 71 + .../site-packages/openpyxl/reader/excel.py | 349 + .../site-packages/openpyxl/reader/strings.py | 44 + .../site-packages/openpyxl/reader/workbook.py | 133 + .../site-packages/openpyxl/styles/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 673 bytes .../__pycache__/alignment.cpython-312.pyc | Bin 0 -> 2522 bytes .../__pycache__/borders.cpython-312.pyc | Bin 0 -> 3720 bytes .../__pycache__/builtins.cpython-312.pyc | Bin 0 -> 33169 bytes .../__pycache__/cell_style.cpython-312.pyc | Bin 0 -> 7613 bytes .../styles/__pycache__/colors.cpython-312.pyc | Bin 0 -> 6455 bytes .../__pycache__/differential.cpython-312.pyc | Bin 0 -> 3500 bytes .../styles/__pycache__/fills.cpython-312.pyc | Bin 0 -> 8994 bytes .../styles/__pycache__/fonts.cpython-312.pyc | Bin 0 -> 4010 bytes .../__pycache__/named_styles.cpython-312.pyc | Bin 0 -> 11070 bytes .../__pycache__/numbers.cpython-312.pyc | Bin 0 -> 7851 bytes .../__pycache__/protection.cpython-312.pyc | Bin 0 -> 833 bytes .../styles/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 2807 bytes .../__pycache__/styleable.cpython-312.pyc | Bin 0 -> 7547 bytes .../__pycache__/stylesheet.cpython-312.pyc | Bin 0 -> 11606 bytes .../styles/__pycache__/table.cpython-312.pyc | Bin 0 -> 3259 bytes .../openpyxl/styles/alignment.py | 62 + .../site-packages/openpyxl/styles/borders.py | 103 + .../site-packages/openpyxl/styles/builtins.py | 1397 +++ .../openpyxl/styles/cell_style.py | 206 + .../site-packages/openpyxl/styles/colors.py | 172 + .../openpyxl/styles/differential.py | 95 + .../site-packages/openpyxl/styles/fills.py | 224 + .../site-packages/openpyxl/styles/fonts.py | 113 + .../openpyxl/styles/named_styles.py | 282 + .../site-packages/openpyxl/styles/numbers.py | 200 + .../openpyxl/styles/protection.py | 17 + .../site-packages/openpyxl/styles/proxy.py | 62 + .../openpyxl/styles/styleable.py | 151 + .../openpyxl/styles/stylesheet.py | 274 + .../site-packages/openpyxl/styles/table.py | 94 + .../site-packages/openpyxl/utils/__init__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 554 bytes .../bound_dictionary.cpython-312.pyc | Bin 0 -> 1361 bytes .../utils/__pycache__/cell.cpython-312.pyc | Bin 0 -> 9864 bytes .../__pycache__/dataframe.cpython-312.pyc | Bin 0 -> 3231 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 6302 bytes .../utils/__pycache__/escape.cpython-312.pyc | Bin 0 -> 1535 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 1883 bytes .../__pycache__/formulas.cpython-312.pyc | Bin 0 -> 4097 bytes .../__pycache__/indexed_list.cpython-312.pyc | Bin 0 -> 2340 bytes .../__pycache__/inference.cpython-312.pyc | Bin 0 -> 2272 bytes .../__pycache__/protection.cpython-312.pyc | Bin 0 -> 1220 bytes .../utils/__pycache__/units.cpython-312.pyc | Bin 0 -> 3110 bytes .../openpyxl/utils/bound_dictionary.py | 26 + venv/Lib/site-packages/openpyxl/utils/cell.py | 240 + .../site-packages/openpyxl/utils/dataframe.py | 87 + .../site-packages/openpyxl/utils/datetime.py | 140 + .../site-packages/openpyxl/utils/escape.py | 43 + .../openpyxl/utils/exceptions.py | 34 + .../site-packages/openpyxl/utils/formulas.py | 24 + .../openpyxl/utils/indexed_list.py | 49 + .../site-packages/openpyxl/utils/inference.py | 60 + .../openpyxl/utils/protection.py | 22 + .../Lib/site-packages/openpyxl/utils/units.py | 108 + .../openpyxl/workbook/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 243 bytes .../__pycache__/_writer.cpython-312.pyc | Bin 0 -> 10561 bytes .../__pycache__/child.cpython-312.pyc | Bin 0 -> 7258 bytes .../__pycache__/defined_name.cpython-312.pyc | Bin 0 -> 7626 bytes .../external_reference.cpython-312.pyc | Bin 0 -> 806 bytes .../function_group.cpython-312.pyc | Bin 0 -> 1359 bytes .../__pycache__/properties.cpython-312.pyc | Bin 0 -> 4681 bytes .../__pycache__/protection.cpython-312.pyc | Bin 0 -> 5887 bytes .../__pycache__/smart_tags.cpython-312.pyc | Bin 0 -> 1924 bytes .../__pycache__/views.cpython-312.pyc | Bin 0 -> 4472 bytes .../workbook/__pycache__/web.cpython-312.pyc | Bin 0 -> 3174 bytes .../__pycache__/workbook.cpython-312.pyc | Bin 0 -> 18846 bytes .../openpyxl/workbook/_writer.py | 197 + .../site-packages/openpyxl/workbook/child.py | 166 + .../openpyxl/workbook/defined_name.py | 189 + .../workbook/external_link/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 261 bytes .../__pycache__/external.cpython-312.pyc | Bin 0 -> 6411 bytes .../workbook/external_link/external.py | 190 + .../openpyxl/workbook/external_reference.py | 18 + .../openpyxl/workbook/function_group.py | 36 + .../openpyxl/workbook/properties.py | 151 + .../openpyxl/workbook/protection.py | 163 + .../openpyxl/workbook/smart_tags.py | 56 + .../site-packages/openpyxl/workbook/views.py | 155 + .../site-packages/openpyxl/workbook/web.py | 98 + .../openpyxl/workbook/workbook.py | 438 + .../openpyxl/worksheet/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 198 bytes .../__pycache__/_read_only.cpython-312.pyc | Bin 0 -> 7546 bytes .../__pycache__/_reader.cpython-312.pyc | Bin 0 -> 22530 bytes .../__pycache__/_write_only.cpython-312.pyc | Bin 0 -> 6603 bytes .../__pycache__/_writer.cpython-312.pyc | Bin 0 -> 19604 bytes .../__pycache__/cell_range.cpython-312.pyc | Bin 0 -> 22841 bytes .../__pycache__/cell_watch.cpython-312.pyc | Bin 0 -> 1178 bytes .../__pycache__/controls.cpython-312.pyc | Bin 0 -> 3124 bytes .../__pycache__/copier.cpython-312.pyc | Bin 0 -> 4131 bytes .../__pycache__/custom.cpython-312.pyc | Bin 0 -> 1212 bytes .../datavalidation.cpython-312.pyc | Bin 0 -> 7801 bytes .../__pycache__/dimensions.cpython-312.pyc | Bin 0 -> 11333 bytes .../__pycache__/drawing.cpython-312.pyc | Bin 0 -> 715 bytes .../__pycache__/errors.cpython-312.pyc | Bin 0 -> 2948 bytes .../__pycache__/filters.cpython-312.pyc | Bin 0 -> 16625 bytes .../__pycache__/formula.cpython-312.pyc | Bin 0 -> 1805 bytes .../__pycache__/header_footer.cpython-312.pyc | Bin 0 -> 10460 bytes .../__pycache__/hyperlink.cpython-312.pyc | Bin 0 -> 1675 bytes .../__pycache__/merge.cpython-312.pyc | Bin 0 -> 6497 bytes .../worksheet/__pycache__/ole.cpython-312.pyc | Bin 0 -> 4016 bytes .../__pycache__/page.cpython-312.pyc | Bin 0 -> 6078 bytes .../__pycache__/pagebreak.cpython-312.pyc | Bin 0 -> 3162 bytes .../__pycache__/picture.cpython-312.pyc | Bin 0 -> 500 bytes .../print_settings.cpython-312.pyc | Bin 0 -> 8998 bytes .../__pycache__/properties.cpython-312.pyc | Bin 0 -> 3144 bytes .../__pycache__/protection.cpython-312.pyc | Bin 0 -> 4442 bytes .../__pycache__/related.cpython-312.pyc | Bin 0 -> 924 bytes .../__pycache__/scenario.cpython-312.pyc | Bin 0 -> 3347 bytes .../__pycache__/smart_tag.cpython-312.pyc | Bin 0 -> 2440 bytes .../__pycache__/table.cpython-312.pyc | Bin 0 -> 14177 bytes .../__pycache__/views.cpython-312.pyc | Bin 0 -> 5071 bytes .../__pycache__/worksheet.cpython-312.pyc | Bin 0 -> 37107 bytes .../openpyxl/worksheet/_read_only.py | 190 + .../openpyxl/worksheet/_reader.py | 472 + .../openpyxl/worksheet/_write_only.py | 160 + .../openpyxl/worksheet/_writer.py | 390 + .../openpyxl/worksheet/cell_range.py | 512 + .../openpyxl/worksheet/cell_watch.py | 34 + .../openpyxl/worksheet/controls.py | 107 + .../openpyxl/worksheet/copier.py | 70 + .../openpyxl/worksheet/custom.py | 35 + .../openpyxl/worksheet/datavalidation.py | 202 + .../openpyxl/worksheet/dimensions.py | 306 + .../openpyxl/worksheet/drawing.py | 14 + .../openpyxl/worksheet/errors.py | 93 + .../openpyxl/worksheet/filters.py | 486 + .../openpyxl/worksheet/formula.py | 51 + .../openpyxl/worksheet/header_footer.py | 270 + .../openpyxl/worksheet/hyperlink.py | 46 + .../site-packages/openpyxl/worksheet/merge.py | 141 + .../site-packages/openpyxl/worksheet/ole.py | 133 + .../site-packages/openpyxl/worksheet/page.py | 174 + .../openpyxl/worksheet/pagebreak.py | 94 + .../openpyxl/worksheet/picture.py | 8 + .../openpyxl/worksheet/print_settings.py | 184 + .../openpyxl/worksheet/properties.py | 97 + .../openpyxl/worksheet/protection.py | 120 + .../openpyxl/worksheet/related.py | 17 + .../openpyxl/worksheet/scenario.py | 105 + .../openpyxl/worksheet/smart_tag.py | 78 + .../site-packages/openpyxl/worksheet/table.py | 385 + .../site-packages/openpyxl/worksheet/views.py | 155 + .../openpyxl/worksheet/worksheet.py | 907 ++ .../site-packages/openpyxl/writer/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 195 bytes .../writer/__pycache__/excel.cpython-312.pyc | Bin 0 -> 16476 bytes .../writer/__pycache__/theme.cpython-312.pyc | Bin 0 -> 10564 bytes .../site-packages/openpyxl/writer/excel.py | 295 + .../site-packages/openpyxl/writer/theme.py | 291 + .../site-packages/openpyxl/xml/__init__.py | 42 + .../xml/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1558 bytes .../xml/__pycache__/constants.cpython-312.pyc | Bin 0 -> 5130 bytes .../xml/__pycache__/functions.cpython-312.pyc | Bin 0 -> 2551 bytes .../site-packages/openpyxl/xml/constants.py | 129 + .../site-packages/openpyxl/xml/functions.py | 87 + .../pip-24.3.1.dist-info/AUTHORS.txt | 799 ++ .../pip-24.3.1.dist-info/INSTALLER | 1 + .../pip-24.3.1.dist-info/LICENSE.txt | 20 + .../pip-24.3.1.dist-info/METADATA | 90 + .../site-packages/pip-24.3.1.dist-info/RECORD | 853 ++ .../pip-24.3.1.dist-info/REQUESTED | 0 .../site-packages/pip-24.3.1.dist-info/WHEEL | 5 + .../pip-24.3.1.dist-info/entry_points.txt | 3 + .../pip-24.3.1.dist-info/top_level.txt | 1 + venv/Lib/site-packages/pip/__init__.py | 13 + venv/Lib/site-packages/pip/__main__.py | 24 + venv/Lib/site-packages/pip/__pip-runner__.py | 50 + .../pip/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 694 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 848 bytes .../__pip-runner__.cpython-312.pyc | Bin 0 -> 2212 bytes .../site-packages/pip/_internal/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 794 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 0 -> 14506 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 12674 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 17639 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 36852 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 677 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 0 -> 5125 bytes .../self_outdated_check.cpython-312.pyc | Bin 0 -> 10215 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 0 -> 13622 bytes .../site-packages/pip/_internal/build_env.py | 319 + venv/Lib/site-packages/pip/_internal/cache.py | 290 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 285 bytes .../autocompletion.cpython-312.pyc | Bin 0 -> 8613 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 0 -> 10201 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 0 -> 30402 bytes .../command_context.cpython-312.pyc | Bin 0 -> 1781 bytes .../__pycache__/index_command.cpython-312.pyc | Bin 0 -> 7131 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 0 -> 2307 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 0 -> 4913 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 0 -> 15047 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 0 -> 3851 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 0 -> 12248 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 0 -> 7840 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 382 bytes .../pip/_internal/cli/autocompletion.py | 176 + .../pip/_internal/cli/base_command.py | 231 + .../pip/_internal/cli/cmdoptions.py | 1075 +++ .../pip/_internal/cli/command_context.py | 27 + .../pip/_internal/cli/index_command.py | 170 + .../site-packages/pip/_internal/cli/main.py | 80 + .../pip/_internal/cli/main_parser.py | 134 + .../site-packages/pip/_internal/cli/parser.py | 294 + .../pip/_internal/cli/progress_bars.py | 94 + .../pip/_internal/cli/req_command.py | 329 + .../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 0 -> 4009 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 9708 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 2599 bytes .../__pycache__/completion.cpython-312.pyc | Bin 0 -> 5200 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 13170 bytes .../__pycache__/debug.cpython-312.pyc | Bin 0 -> 10075 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 7510 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 4392 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 0 -> 2975 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 0 -> 1680 bytes .../__pycache__/index.cpython-312.pyc | Bin 0 -> 6678 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 0 -> 3987 bytes .../__pycache__/install.cpython-312.pyc | Bin 0 -> 29121 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 0 -> 15764 bytes .../__pycache__/search.cpython-312.pyc | Bin 0 -> 7525 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 0 -> 10484 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 0 -> 4716 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 8872 bytes .../pip/_internal/commands/cache.py | 225 + .../pip/_internal/commands/check.py | 67 + .../pip/_internal/commands/completion.py | 130 + .../pip/_internal/commands/configuration.py | 280 + .../pip/_internal/commands/debug.py | 201 + .../pip/_internal/commands/download.py | 146 + .../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 | 783 ++ .../pip/_internal/commands/list.py | 375 + .../pip/_internal/commands/search.py | 172 + .../pip/_internal/commands/show.py | 217 + .../pip/_internal/commands/uninstall.py | 114 + .../pip/_internal/commands/wheel.py | 182 + .../pip/_internal/configuration.py | 383 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 948 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 2900 bytes .../__pycache__/installed.cpython-312.pyc | Bin 0 -> 1707 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 0 -> 8434 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 2288 bytes .../pip/_internal/distributions/base.py | 53 + .../pip/_internal/distributions/installed.py | 29 + .../pip/_internal/distributions/sdist.py | 158 + .../pip/_internal/distributions/wheel.py | 42 + .../site-packages/pip/_internal/exceptions.py | 809 ++ .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 239 bytes .../__pycache__/collector.cpython-312.pyc | Bin 0 -> 21624 bytes .../package_finder.cpython-312.pyc | Bin 0 -> 40655 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 0 -> 12531 bytes .../pip/_internal/index/collector.py | 494 + .../pip/_internal/index/package_finder.py | 1020 ++ .../pip/_internal/index/sources.py | 284 + .../pip/_internal/locations/__init__.py | 456 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 16447 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 0 -> 6798 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 0 -> 8035 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3788 bytes .../pip/_internal/locations/_distutils.py | 172 + .../pip/_internal/locations/_sysconfig.py | 214 + .../pip/_internal/locations/base.py | 81 + venv/Lib/site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 128 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5876 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 2933 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 0 -> 35205 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 0 -> 16091 bytes .../pip/_internal/metadata/_json.py | 84 + .../pip/_internal/metadata/base.py | 688 ++ .../_internal/metadata/importlib/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 365 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 4498 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 0 -> 12572 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 0 -> 11086 bytes .../_internal/metadata/importlib/_compat.py | 85 + .../_internal/metadata/importlib/_dists.py | 221 + .../pip/_internal/metadata/importlib/_envs.py | 189 + .../pip/_internal/metadata/pkg_resources.py | 301 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 273 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 0 -> 1611 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 0 -> 10851 bytes .../format_control.cpython-312.pyc | Bin 0 -> 4230 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 0 -> 1701 bytes .../installation_report.cpython-312.pyc | Bin 0 -> 2284 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 0 -> 26624 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 0 -> 1030 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 0 -> 4994 bytes .../selection_prefs.cpython-312.pyc | Bin 0 -> 1858 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 0 -> 4960 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 6559 bytes .../pip/_internal/models/candidate.py | 25 + .../pip/_internal/models/direct_url.py | 224 + .../pip/_internal/models/format_control.py | 78 + .../pip/_internal/models/index.py | 28 + .../_internal/models/installation_report.py | 56 + .../pip/_internal/models/link.py | 590 ++ .../pip/_internal/models/scheme.py | 25 + .../pip/_internal/models/search_scope.py | 127 + .../pip/_internal/models/selection_prefs.py | 53 + .../pip/_internal/models/target_python.py | 121 + .../pip/_internal/models/wheel.py | 118 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 261 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 0 -> 22106 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 0 -> 6458 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 8486 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 0 -> 11614 bytes .../__pycache__/session.cpython-312.pyc | Bin 0 -> 18881 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2262 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 0 -> 2956 bytes .../pip/_internal/network/auth.py | 566 ++ .../pip/_internal/network/cache.py | 106 + .../pip/_internal/network/download.py | 187 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 522 + .../pip/_internal/network/utils.py | 98 + .../pip/_internal/network/xmlrpc.py | 62 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 204 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 7111 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 10135 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 0 -> 25779 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 210 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 0 -> 7674 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 1864 bytes .../metadata_editable.cpython-312.pyc | Bin 0 -> 1898 bytes .../metadata_legacy.cpython-312.pyc | Bin 0 -> 3018 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1684 bytes .../wheel_editable.cpython-312.pyc | Bin 0 -> 2023 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 0 -> 3853 bytes .../operations/build/build_tracker.py | 138 + .../_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 | 181 + .../pip/_internal/operations/freeze.py | 258 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 273 bytes .../editable_legacy.cpython-312.pyc | Bin 0 -> 1805 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 34110 bytes .../operations/install/editable_legacy.py | 47 + .../pip/_internal/operations/install/wheel.py | 741 ++ .../pip/_internal/operations/prepare.py | 732 ++ .../site-packages/pip/_internal/pyproject.py | 185 + .../pip/_internal/req/__init__.py | 90 + .../req/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3452 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 0 -> 21262 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 0 -> 22130 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 0 -> 38482 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 0 -> 5490 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 0 -> 32101 bytes .../pip/_internal/req/constructors.py | 560 ++ .../pip/_internal/req/req_file.py | 574 ++ .../pip/_internal/req/req_install.py | 934 ++ .../pip/_internal/req/req_set.py | 82 + .../pip/_internal/req/req_uninstall.py | 633 ++ .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 204 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 1192 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 211 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 22586 bytes .../_internal/resolution/legacy/resolver.py | 597 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 215 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 8156 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 0 -> 29415 bytes .../__pycache__/factory.cpython-312.pyc | Bin 0 -> 32526 bytes .../found_candidates.cpython-312.pyc | Bin 0 -> 6800 bytes .../__pycache__/provider.cpython-312.pyc | Bin 0 -> 10530 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 0 -> 5047 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 15363 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 12321 bytes .../_internal/resolution/resolvelib/base.py | 139 + .../resolution/resolvelib/candidates.py | 574 ++ .../resolution/resolvelib/factory.py | 823 ++ .../resolution/resolvelib/found_candidates.py | 174 + .../resolution/resolvelib/provider.py | 258 + .../resolution/resolvelib/reporter.py | 81 + .../resolution/resolvelib/requirements.py | 245 + .../resolution/resolvelib/resolver.py | 317 + .../pip/_internal/self_outdated_check.py | 244 + .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 199 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 0 -> 4534 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 0 -> 1870 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 0 -> 2414 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 0 -> 2911 bytes .../compatibility_tags.cpython-312.pyc | Bin 0 -> 6354 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 688 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 0 -> 4195 bytes .../direct_url_helpers.cpython-312.pyc | Bin 0 -> 3540 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 0 -> 3210 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2152 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 0 -> 3997 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 0 -> 7333 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 0 -> 1168 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 0 -> 2423 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 0 -> 7607 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13562 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 0 -> 33455 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 0 -> 2587 bytes .../utils/__pycache__/retry.cpython-312.pyc | Bin 0 -> 2112 bytes .../setuptools_build.cpython-312.pyc | Bin 0 -> 4554 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 0 -> 8643 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 0 -> 12028 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 0 -> 13502 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 0 -> 2081 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 0 -> 4470 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5907 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 | 79 + .../pip/_internal/utils/compatibility_tags.py | 188 + .../pip/_internal/utils/datetime.py | 11 + .../pip/_internal/utils/deprecation.py | 124 + .../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 | 149 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 101 + .../pip/_internal/utils/hashes.py | 147 + .../pip/_internal/utils/logging.py | 347 + .../site-packages/pip/_internal/utils/misc.py | 772 ++ .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/retry.py | 42 + .../pip/_internal/utils/setuptools_build.py | 146 + .../pip/_internal/utils/subprocess.py | 245 + .../pip/_internal/utils/temp_dir.py | 296 + .../pip/_internal/utils/unpacking.py | 337 + .../site-packages/pip/_internal/utils/urls.py | 55 + .../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 0 -> 538 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 0 -> 5059 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 0 -> 19024 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 0 -> 7612 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 0 -> 12531 bytes .../versioncontrol.cpython-312.pyc | Bin 0 -> 29004 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../site-packages/pip/_internal/vcs/git.py | 527 + .../pip/_internal/vcs/mercurial.py | 163 + .../pip/_internal/vcs/subversion.py | 324 + .../pip/_internal/vcs/versioncontrol.py | 688 ++ .../pip/_internal/wheel_builder.py | 354 + .../Lib/site-packages/pip/_vendor/__init__.py | 116 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4557 bytes .../typing_extensions.cpython-312.pyc | Bin 0 -> 139459 bytes .../pip/_vendor/cachecontrol/__init__.py | 28 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 910 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 0 -> 2654 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 0 -> 6472 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 3795 bytes .../__pycache__/controller.cpython-312.pyc | Bin 0 -> 16232 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 0 -> 4355 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 0 -> 6702 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 0 -> 5269 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 0 -> 1682 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 0 -> 443 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 0 -> 7771 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 0 -> 2741 bytes .../_vendor/cachecontrol/caches/file_cache.py | 182 + .../cachecontrol/caches/redis_cache.py | 48 + .../pip/_vendor/cachecontrol/controller.py | 499 + .../pip/_vendor/cachecontrol/filewrapper.py | 119 + .../pip/_vendor/cachecontrol/heuristics.py | 154 + .../pip/_vendor/cachecontrol/py.typed | 0 .../pip/_vendor/cachecontrol/serialize.py | 146 + .../pip/_vendor/cachecontrol/wrapper.py | 43 + .../pip/_vendor/certifi/__init__.py | 4 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 326 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 653 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 3219 bytes .../pip/_vendor/certifi/cacert.pem | 4929 ++++++++++ .../site-packages/pip/_vendor/certifi/core.py | 114 + .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/distlib/__init__.py | 33 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1277 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 45534 bytes .../__pycache__/database.cpython-312.pyc | Bin 0 -> 65589 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 0 -> 24324 bytes .../__pycache__/locators.cpython-312.pyc | Bin 0 -> 59869 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 0 -> 15084 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 7662 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 41568 bytes .../__pycache__/resources.cpython-312.pyc | Bin 0 -> 17320 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 0 -> 19761 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 0 -> 88043 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 30352 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 52553 bytes .../pip/_vendor/distlib/compat.py | 1137 +++ .../pip/_vendor/distlib/database.py | 1329 +++ .../pip/_vendor/distlib/index.py | 508 + .../pip/_vendor/distlib/locators.py | 1295 +++ .../pip/_vendor/distlib/manifest.py | 384 + .../pip/_vendor/distlib/markers.py | 162 + .../pip/_vendor/distlib/metadata.py | 1031 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 447 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 97792 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 182784 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 108032 bytes .../site-packages/pip/_vendor/distlib/util.py | 1984 ++++ .../pip/_vendor/distlib/version.py | 750 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 91648 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 168448 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 101888 bytes .../pip/_vendor/distlib/wheel.py | 1100 +++ .../pip/_vendor/distro/__init__.py | 54 + .../pip/_vendor/distro/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 968 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 300 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 0 -> 53800 bytes .../pip/_vendor/distro/distro.py | 1403 +++ .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 889 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4984 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 895 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 15799 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99484 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2641 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 224 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158856 bytes .../site-packages/pip/_vendor/idna/codec.py | 118 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 395 + .../pip/_vendor/idna/idnadata.py | 4245 ++++++++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 8598 +++++++++++++++++ .../pip/_vendor/msgpack/__init__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1749 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 2033 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 0 -> 8178 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 0 -> 42051 bytes .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 168 + .../pip/_vendor/msgpack/fallback.py | 951 ++ .../pip/_vendor/packaging/__init__.py | 15 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 566 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 0 -> 4975 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 9693 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 4562 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 13993 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3249 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 0 -> 7923 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 11019 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 24961 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 4418 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 38747 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 23227 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 7349 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19515 bytes .../pip/_vendor/packaging/_elffile.py | 110 + .../pip/_vendor/packaging/_manylinux.py | 262 + .../pip/_vendor/packaging/_musllinux.py | 85 + .../pip/_vendor/packaging/_parser.py | 354 + .../pip/_vendor/packaging/_structures.py | 61 + .../pip/_vendor/packaging/_tokenizer.py | 194 + .../pip/_vendor/packaging/markers.py | 325 + .../pip/_vendor/packaging/metadata.py | 804 ++ .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 91 + .../pip/_vendor/packaging/specifiers.py | 1009 ++ .../pip/_vendor/packaging/tags.py | 627 ++ .../pip/_vendor/packaging/utils.py | 174 + .../pip/_vendor/packaging/version.py | 563 ++ .../pip/_vendor/pkg_resources/__init__.py | 3676 +++++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 161269 bytes .../pip/_vendor/platformdirs/__init__.py | 627 ++ .../pip/_vendor/platformdirs/__main__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19837 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 1956 bytes .../__pycache__/android.cpython-312.pyc | Bin 0 -> 10705 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 12919 bytes .../__pycache__/macos.cpython-312.pyc | Bin 0 -> 8015 bytes .../__pycache__/unix.cpython-312.pyc | Bin 0 -> 15045 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 605 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 13682 bytes .../pip/_vendor/platformdirs/android.py | 249 + .../pip/_vendor/platformdirs/api.py | 292 + .../pip/_vendor/platformdirs/macos.py | 130 + .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 275 + .../pip/_vendor/platformdirs/version.py | 16 + .../pip/_vendor/platformdirs/windows.py | 272 + .../pip/_vendor/pygments/__init__.py | 82 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3497 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 743 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 0 -> 26593 bytes .../__pycache__/console.cpython-312.pyc | Bin 0 -> 2637 bytes .../__pycache__/filter.cpython-312.pyc | Bin 0 -> 3230 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 0 -> 4729 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 38370 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 0 -> 1568 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 0 -> 2617 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 0 -> 4086 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 0 -> 4765 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 0 -> 12107 bytes .../__pycache__/style.cpython-312.pyc | Bin 0 -> 6702 bytes .../__pycache__/token.cpython-312.pyc | Bin 0 -> 8198 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 0 -> 32981 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 0 -> 14078 bytes .../pip/_vendor/pygments/cmdline.py | 668 ++ .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 70 + .../pip/_vendor/pygments/filters/__init__.py | 940 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 37920 bytes .../pip/_vendor/pygments/formatter.py | 129 + .../_vendor/pygments/formatters/__init__.py | 157 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6911 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 4224 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 0 -> 4231 bytes .../__pycache__/groff.cpython-312.pyc | Bin 0 -> 7302 bytes .../__pycache__/html.cpython-312.pyc | Bin 0 -> 41035 bytes .../__pycache__/img.cpython-312.pyc | Bin 0 -> 28557 bytes .../__pycache__/irc.cpython-312.pyc | Bin 0 -> 6064 bytes .../__pycache__/latex.cpython-312.pyc | Bin 0 -> 20134 bytes .../__pycache__/other.cpython-312.pyc | Bin 0 -> 6886 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 0 -> 2967 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 0 -> 13782 bytes .../__pycache__/svg.cpython-312.pyc | Bin 0 -> 9148 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 0 -> 5828 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 0 -> 15127 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 | 987 ++ .../pip/_vendor/pygments/formatters/img.py | 685 ++ .../pip/_vendor/pygments/formatters/irc.py | 154 + .../pip/_vendor/pygments/formatters/latex.py | 518 + .../pip/_vendor/pygments/formatters/other.py | 160 + .../pygments/formatters/pangomarkup.py | 83 + .../pip/_vendor/pygments/formatters/rtf.py | 349 + .../pip/_vendor/pygments/formatters/svg.py | 185 + .../_vendor/pygments/formatters/terminal.py | 127 + .../pygments/formatters/terminal256.py | 338 + .../pip/_vendor/pygments/lexer.py | 963 ++ .../pip/_vendor/pygments/lexers/__init__.py | 362 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 14630 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 68272 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 0 -> 42976 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 589 ++ .../pip/_vendor/pygments/lexers/python.py | 1198 +++ .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 72 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 247 + .../pip/_vendor/pygments/style.py | 203 + .../pip/_vendor/pygments/styles/__init__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2673 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 3657 bytes .../pip/_vendor/pygments/styles/_mapping.py | 54 + .../pip/_vendor/pygments/token.py | 214 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 324 + .../pip/_vendor/pyproject_hooks/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 622 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 383 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 0 -> 14702 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 0 -> 1089 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 0 -> 14362 bytes .../_in_process/_in_process.py | 353 + .../pip/_vendor/requests/__init__.py | 179 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5262 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 593 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2033 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 28440 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7200 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13930 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 931 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 1686 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25207 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7607 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4237 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1060 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35437 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1275 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27855 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6032 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5632 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36375 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 50 + .../pip/_vendor/requests/adapters.py | 719 ++ .../site-packages/pip/_vendor/requests/api.py | 157 + .../pip/_vendor/requests/auth.py | 314 + .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/compat.py | 78 + .../pip/_vendor/requests/cookies.py | 561 ++ .../pip/_vendor/requests/exceptions.py | 151 + .../pip/_vendor/requests/help.py | 127 + .../pip/_vendor/requests/hooks.py | 33 + .../pip/_vendor/requests/models.py | 1037 ++ .../pip/_vendor/requests/packages.py | 25 + .../pip/_vendor/requests/sessions.py | 831 ++ .../pip/_vendor/requests/status_codes.py | 128 + .../pip/_vendor/requests/structures.py | 99 + .../pip/_vendor/requests/utils.py | 1096 +++ .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 643 bytes .../__pycache__/providers.cpython-312.pyc | Bin 0 -> 6860 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 0 -> 2663 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 0 -> 25889 bytes .../__pycache__/structs.cpython-312.pyc | Bin 0 -> 10509 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 209 bytes .../collections_abc.cpython-312.pyc | Bin 0 -> 429 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/py.typed | 0 .../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 | 273 + .../rich/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7024 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 10301 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 0 -> 7881 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 0 -> 205985 bytes .../_emoji_replace.cpython-312.pyc | Bin 0 -> 1738 bytes .../_export_format.cpython-312.pyc | Bin 0 -> 2358 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 0 -> 546 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 0 -> 864 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 0 -> 12082 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 0 -> 4156 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 0 -> 1879 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 0 -> 3629 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 0 -> 5169 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 0 -> 730 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 0 -> 6579 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 0 -> 13188 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 0 -> 974 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 0 -> 874 bytes .../_win32_console.cpython-312.pyc | Bin 0 -> 28985 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 0 -> 2499 bytes .../_windows_renderer.cpython-312.pyc | Bin 0 -> 3572 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 0 -> 3335 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 0 -> 1617 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 0 -> 12296 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 9075 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 0 -> 4281 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 0 -> 11847 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 0 -> 5819 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 0 -> 26578 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 0 -> 1710 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 0 -> 8593 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 0 -> 113445 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 0 -> 2267 bytes .../__pycache__/containers.cpython-312.pyc | Bin 0 -> 9219 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 0 -> 10950 bytes .../default_styles.cpython-312.pyc | Bin 0 -> 10375 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 0 -> 1497 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 0 -> 4221 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1854 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 0 -> 3580 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 0 -> 3081 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 0 -> 9896 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 0 -> 6044 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 0 -> 5217 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 0 -> 20167 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 0 -> 19018 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 0 -> 4898 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13563 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 0 -> 9576 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 0 -> 6387 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 0 -> 7133 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 0 -> 1820 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 0 -> 5306 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 0 -> 12192 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 0 -> 40156 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 0 -> 74944 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 0 -> 10386 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 0 -> 14796 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1801 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 0 -> 576 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 0 -> 6622 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 0 -> 6577 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 0 -> 3834 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 0 -> 2488 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 0 -> 28124 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 0 -> 6073 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 0 -> 6070 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 0 -> 33509 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 0 -> 2148 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 0 -> 39957 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 0 -> 43548 bytes .../terminal_theme.cpython-312.pyc | Bin 0 -> 3357 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 0 -> 60858 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 0 -> 6344 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 0 -> 323 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 0 -> 31520 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 0 -> 11445 bytes .../pip/_vendor/rich/_cell_widths.py | 454 + .../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 | 159 + .../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 | 71 + .../pip/_vendor/rich/_windows_renderer.py | 56 + .../site-packages/pip/_vendor/rich/_wrap.py | 93 + .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 311 + .../site-packages/pip/_vendor/rich/ansi.py | 240 + .../Lib/site-packages/pip/_vendor/rich/bar.py | 93 + .../Lib/site-packages/pip/_vendor/rich/box.py | 480 + .../site-packages/pip/_vendor/rich/cells.py | 167 + .../site-packages/pip/_vendor/rich/color.py | 621 ++ .../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 | 139 + .../site-packages/pip/_vendor/rich/jupyter.py | 101 + .../site-packages/pip/_vendor/rich/layout.py | 442 + .../site-packages/pip/_vendor/rich/live.py | 375 + .../pip/_vendor/rich/live_render.py | 112 + .../site-packages/pip/_vendor/rich/logging.py | 289 + .../site-packages/pip/_vendor/rich/markup.py | 251 + .../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 | 312 + .../site-packages/pip/_vendor/rich/pretty.py | 995 ++ .../pip/_vendor/rich/progress.py | 1699 ++++ .../pip/_vendor/rich/progress_bar.py | 223 + .../site-packages/pip/_vendor/rich/prompt.py | 375 + .../pip/_vendor/rich/protocol.py | 42 + .../site-packages/pip/_vendor/rich/py.typed | 0 .../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 | 738 ++ .../site-packages/pip/_vendor/rich/spinner.py | 137 + .../site-packages/pip/_vendor/rich/status.py | 131 + .../site-packages/pip/_vendor/rich/style.py | 796 ++ .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 958 ++ .../site-packages/pip/_vendor/rich/table.py | 1000 ++ .../pip/_vendor/rich/terminal_theme.py | 153 + .../site-packages/pip/_vendor/rich/text.py | 1357 +++ .../site-packages/pip/_vendor/rich/theme.py | 115 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 753 ++ .../site-packages/pip/_vendor/rich/tree.py | 249 + .../pip/_vendor/tomli/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 393 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 0 -> 26908 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 0 -> 3917 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 0 -> 375 bytes .../pip/_vendor/tomli/_parser.py | 691 ++ .../site-packages/pip/_vendor/tomli/_re.py | 107 + .../site-packages/pip/_vendor/tomli/_types.py | 10 + .../site-packages/pip/_vendor/tomli/py.typed | 1 + .../pip/_vendor/truststore/__init__.py | 36 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1353 bytes .../__pycache__/_api.cpython-312.pyc | Bin 0 -> 16782 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 0 -> 18996 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 0 -> 2214 bytes .../_ssl_constants.cpython-312.pyc | Bin 0 -> 1108 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 0 -> 15774 bytes .../pip/_vendor/truststore/_api.py | 316 + .../pip/_vendor/truststore/_macos.py | 571 ++ .../pip/_vendor/truststore/_openssl.py | 66 + .../pip/_vendor/truststore/_ssl_constants.py | 31 + .../pip/_vendor/truststore/_windows.py | 567 ++ .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/typing_extensions.py | 3641 +++++++ .../pip/_vendor/urllib3/__init__.py | 102 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3414 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 16373 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 227 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 20412 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 36547 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 13502 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 10411 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 4021 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 20438 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 7303 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 33952 bytes .../pip/_vendor/urllib3/_collections.py | 355 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 572 ++ .../pip/_vendor/urllib3/connectionpool.py | 1140 +++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 207 bytes .../_appengine_environ.cpython-312.pyc | Bin 0 -> 1857 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 0 -> 11573 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 0 -> 5723 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 24457 bytes .../securetransport.cpython-312.pyc | Bin 0 -> 35510 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 7520 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 224 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 0 -> 17436 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 0 -> 14772 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 | 920 ++ .../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 0 -> 208 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 0 -> 41264 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 218 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 0 -> 1834 bytes .../weakref_finalize.cpython-312.pyc | Bin 0 -> 7345 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 | 540 ++ .../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 0 -> 1155 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4756 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1561 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 0 -> 1361 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 4192 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 3001 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 21731 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 15373 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5060 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 10762 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11148 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 15794 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 4412 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 | 504 + .../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 + venv/Lib/site-packages/pip/_vendor/vendor.txt | 18 + venv/Lib/site-packages/pip/py.typed | 4 + .../sqlparse-0.5.3.dist-info/INSTALLER | 1 + .../sqlparse-0.5.3.dist-info/METADATA | 113 + .../sqlparse-0.5.3.dist-info/RECORD | 50 + .../sqlparse-0.5.3.dist-info/WHEEL | 4 + .../sqlparse-0.5.3.dist-info/entry_points.txt | 2 + .../sqlparse-0.5.3.dist-info/licenses/AUTHORS | 86 + .../sqlparse-0.5.3.dist-info/licenses/LICENSE | 25 + venv/Lib/site-packages/sqlparse/__init__.py | 72 + venv/Lib/site-packages/sqlparse/__main__.py | 22 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3102 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 658 bytes .../sqlparse/__pycache__/cli.cpython-312.pyc | Bin 0 -> 7419 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 484 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 0 -> 8363 bytes .../__pycache__/keywords.cpython-312.pyc | Bin 0 -> 51135 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 6774 bytes .../sqlparse/__pycache__/sql.cpython-312.pyc | Bin 0 -> 31765 bytes .../__pycache__/tokens.cpython-312.pyc | Bin 0 -> 2279 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 4586 bytes venv/Lib/site-packages/sqlparse/cli.py | 203 + .../site-packages/sqlparse/engine/__init__.py | 16 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 431 bytes .../__pycache__/filter_stack.cpython-312.pyc | Bin 0 -> 2233 bytes .../__pycache__/grouping.cpython-312.pyc | Bin 0 -> 25091 bytes .../statement_splitter.cpython-312.pyc | Bin 0 -> 3992 bytes .../sqlparse/engine/filter_stack.py | 51 + .../site-packages/sqlparse/engine/grouping.py | 486 + .../sqlparse/engine/statement_splitter.py | 115 + venv/Lib/site-packages/sqlparse/exceptions.py | 12 + .../sqlparse/filters/__init__.py | 42 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1021 bytes .../aligned_indent.cpython-312.pyc | Bin 0 -> 7945 bytes .../__pycache__/others.cpython-312.pyc | Bin 0 -> 9987 bytes .../__pycache__/output.cpython-312.pyc | Bin 0 -> 6516 bytes .../__pycache__/reindent.cpython-312.pyc | Bin 0 -> 15570 bytes .../__pycache__/right_margin.cpython-312.pyc | Bin 0 -> 2214 bytes .../__pycache__/tokens.cpython-312.pyc | Bin 0 -> 2915 bytes .../sqlparse/filters/aligned_indent.py | 135 + .../site-packages/sqlparse/filters/others.py | 172 + .../site-packages/sqlparse/filters/output.py | 122 + .../sqlparse/filters/reindent.py | 247 + .../sqlparse/filters/right_margin.py | 48 + .../site-packages/sqlparse/filters/tokens.py | 59 + venv/Lib/site-packages/sqlparse/formatter.py | 204 + venv/Lib/site-packages/sqlparse/keywords.py | 1002 ++ venv/Lib/site-packages/sqlparse/lexer.py | 161 + venv/Lib/site-packages/sqlparse/sql.py | 660 ++ venv/Lib/site-packages/sqlparse/tokens.py | 71 + venv/Lib/site-packages/sqlparse/utils.py | 124 + .../tzdata-2025.2.dist-info/INSTALLER | 1 + .../tzdata-2025.2.dist-info/METADATA | 34 + .../tzdata-2025.2.dist-info/RECORD | 656 ++ .../tzdata-2025.2.dist-info/WHEEL | 6 + .../tzdata-2025.2.dist-info/licenses/LICENSE | 15 + .../licenses/licenses/LICENSE_APACHE | 201 + .../tzdata-2025.2.dist-info/top_level.txt | 1 + venv/Lib/site-packages/tzdata/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 247 bytes .../tzdata/zoneinfo/Africa/Abidjan | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Accra | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Addis_Ababa | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Algiers | Bin 0 -> 470 bytes .../tzdata/zoneinfo/Africa/Asmara | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Asmera | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Bamako | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Bangui | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Banjul | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Bissau | Bin 0 -> 149 bytes .../tzdata/zoneinfo/Africa/Blantyre | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Brazzaville | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Bujumbura | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Cairo | Bin 0 -> 1309 bytes .../tzdata/zoneinfo/Africa/Casablanca | Bin 0 -> 1919 bytes .../tzdata/zoneinfo/Africa/Ceuta | Bin 0 -> 562 bytes .../tzdata/zoneinfo/Africa/Conakry | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Dakar | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Dar_es_Salaam | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Djibouti | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Douala | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/El_Aaiun | Bin 0 -> 1830 bytes .../tzdata/zoneinfo/Africa/Freetown | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Gaborone | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Harare | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Johannesburg | Bin 0 -> 190 bytes .../site-packages/tzdata/zoneinfo/Africa/Juba | Bin 0 -> 458 bytes .../tzdata/zoneinfo/Africa/Kampala | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Khartoum | Bin 0 -> 458 bytes .../tzdata/zoneinfo/Africa/Kigali | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Kinshasa | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Lagos | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Libreville | Bin 0 -> 180 bytes .../site-packages/tzdata/zoneinfo/Africa/Lome | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Luanda | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Lubumbashi | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Lusaka | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Malabo | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Maputo | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Maseru | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Africa/Mbabane | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Africa/Mogadishu | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Monrovia | Bin 0 -> 164 bytes .../tzdata/zoneinfo/Africa/Nairobi | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Ndjamena | Bin 0 -> 160 bytes .../tzdata/zoneinfo/Africa/Niamey | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Nouakchott | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Ouagadougou | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Porto-Novo | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Sao_Tome | Bin 0 -> 173 bytes .../tzdata/zoneinfo/Africa/Timbuktu | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Tripoli | Bin 0 -> 431 bytes .../tzdata/zoneinfo/Africa/Tunis | Bin 0 -> 449 bytes .../tzdata/zoneinfo/Africa/Windhoek | Bin 0 -> 638 bytes .../tzdata/zoneinfo/Africa/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes .../tzdata/zoneinfo/America/Adak | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Anchorage | Bin 0 -> 977 bytes .../tzdata/zoneinfo/America/Anguilla | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Antigua | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Araguaina | Bin 0 -> 592 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/Catamarca | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Cordoba | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Jujuy | Bin 0 -> 690 bytes .../zoneinfo/America/Argentina/La_Rioja | Bin 0 -> 717 bytes .../tzdata/zoneinfo/America/Argentina/Mendoza | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Salta | Bin 0 -> 690 bytes .../zoneinfo/America/Argentina/San_Juan | Bin 0 -> 717 bytes .../zoneinfo/America/Argentina/San_Luis | Bin 0 -> 717 bytes .../tzdata/zoneinfo/America/Argentina/Tucuman | Bin 0 -> 726 bytes .../tzdata/zoneinfo/America/Argentina/Ushuaia | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 213 bytes .../tzdata/zoneinfo/America/Aruba | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Asuncion | Bin 0 -> 1085 bytes .../tzdata/zoneinfo/America/Atikokan | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Atka | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Bahia | Bin 0 -> 682 bytes .../tzdata/zoneinfo/America/Bahia_Banderas | Bin 0 -> 700 bytes .../tzdata/zoneinfo/America/Barbados | Bin 0 -> 278 bytes .../tzdata/zoneinfo/America/Belem | Bin 0 -> 394 bytes .../tzdata/zoneinfo/America/Belize | Bin 0 -> 1045 bytes .../tzdata/zoneinfo/America/Blanc-Sablon | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Boa_Vista | Bin 0 -> 430 bytes .../tzdata/zoneinfo/America/Bogota | Bin 0 -> 179 bytes .../tzdata/zoneinfo/America/Boise | Bin 0 -> 999 bytes .../tzdata/zoneinfo/America/Buenos_Aires | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Cambridge_Bay | Bin 0 -> 883 bytes .../tzdata/zoneinfo/America/Campo_Grande | Bin 0 -> 952 bytes .../tzdata/zoneinfo/America/Cancun | Bin 0 -> 538 bytes .../tzdata/zoneinfo/America/Caracas | Bin 0 -> 190 bytes .../tzdata/zoneinfo/America/Catamarca | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Cayenne | Bin 0 -> 151 bytes .../tzdata/zoneinfo/America/Cayman | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Chicago | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/America/Chihuahua | Bin 0 -> 691 bytes .../tzdata/zoneinfo/America/Ciudad_Juarez | Bin 0 -> 718 bytes .../tzdata/zoneinfo/America/Coral_Harbour | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Cordoba | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Costa_Rica | Bin 0 -> 232 bytes .../tzdata/zoneinfo/America/Coyhaique | Bin 0 -> 1362 bytes .../tzdata/zoneinfo/America/Creston | Bin 0 -> 240 bytes .../tzdata/zoneinfo/America/Cuiaba | Bin 0 -> 934 bytes .../tzdata/zoneinfo/America/Curacao | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Danmarkshavn | Bin 0 -> 447 bytes .../tzdata/zoneinfo/America/Dawson | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/America/Dawson_Creek | Bin 0 -> 683 bytes .../tzdata/zoneinfo/America/Denver | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/America/Detroit | Bin 0 -> 899 bytes .../tzdata/zoneinfo/America/Dominica | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Edmonton | Bin 0 -> 970 bytes .../tzdata/zoneinfo/America/Eirunepe | Bin 0 -> 436 bytes .../tzdata/zoneinfo/America/El_Salvador | Bin 0 -> 176 bytes .../tzdata/zoneinfo/America/Ensenada | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Fort_Nelson | Bin 0 -> 1448 bytes .../tzdata/zoneinfo/America/Fort_Wayne | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Fortaleza | Bin 0 -> 484 bytes .../tzdata/zoneinfo/America/Glace_Bay | Bin 0 -> 880 bytes .../tzdata/zoneinfo/America/Godthab | Bin 0 -> 965 bytes .../tzdata/zoneinfo/America/Goose_Bay | Bin 0 -> 1580 bytes .../tzdata/zoneinfo/America/Grand_Turk | Bin 0 -> 853 bytes .../tzdata/zoneinfo/America/Grenada | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Guadeloupe | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Guatemala | Bin 0 -> 212 bytes .../tzdata/zoneinfo/America/Guayaquil | Bin 0 -> 179 bytes .../tzdata/zoneinfo/America/Guyana | Bin 0 -> 181 bytes .../tzdata/zoneinfo/America/Halifax | Bin 0 -> 1672 bytes .../tzdata/zoneinfo/America/Havana | Bin 0 -> 1117 bytes .../tzdata/zoneinfo/America/Hermosillo | Bin 0 -> 258 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Indiana/Knox | Bin 0 -> 1016 bytes .../tzdata/zoneinfo/America/Indiana/Marengo | Bin 0 -> 567 bytes .../zoneinfo/America/Indiana/Petersburg | Bin 0 -> 683 bytes .../tzdata/zoneinfo/America/Indiana/Tell_City | Bin 0 -> 522 bytes .../tzdata/zoneinfo/America/Indiana/Vevay | Bin 0 -> 369 bytes .../tzdata/zoneinfo/America/Indiana/Vincennes | Bin 0 -> 558 bytes .../tzdata/zoneinfo/America/Indiana/Winamac | Bin 0 -> 603 bytes .../zoneinfo/America/Indiana/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 211 bytes .../tzdata/zoneinfo/America/Indianapolis | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Inuvik | Bin 0 -> 817 bytes .../tzdata/zoneinfo/America/Iqaluit | Bin 0 -> 855 bytes .../tzdata/zoneinfo/America/Jamaica | Bin 0 -> 339 bytes .../tzdata/zoneinfo/America/Jujuy | Bin 0 -> 690 bytes .../tzdata/zoneinfo/America/Juneau | Bin 0 -> 966 bytes .../zoneinfo/America/Kentucky/Louisville | Bin 0 -> 1242 bytes .../zoneinfo/America/Kentucky/Monticello | Bin 0 -> 972 bytes .../zoneinfo/America/Kentucky/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 212 bytes .../tzdata/zoneinfo/America/Knox_IN | Bin 0 -> 1016 bytes .../tzdata/zoneinfo/America/Kralendijk | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/La_Paz | Bin 0 -> 170 bytes .../tzdata/zoneinfo/America/Lima | Bin 0 -> 283 bytes .../tzdata/zoneinfo/America/Los_Angeles | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Louisville | Bin 0 -> 1242 bytes .../tzdata/zoneinfo/America/Lower_Princes | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Maceio | Bin 0 -> 502 bytes .../tzdata/zoneinfo/America/Managua | Bin 0 -> 295 bytes .../tzdata/zoneinfo/America/Manaus | Bin 0 -> 412 bytes .../tzdata/zoneinfo/America/Marigot | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Martinique | Bin 0 -> 178 bytes .../tzdata/zoneinfo/America/Matamoros | Bin 0 -> 437 bytes .../tzdata/zoneinfo/America/Mazatlan | Bin 0 -> 690 bytes .../tzdata/zoneinfo/America/Mendoza | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Menominee | Bin 0 -> 917 bytes .../tzdata/zoneinfo/America/Merida | Bin 0 -> 654 bytes .../tzdata/zoneinfo/America/Metlakatla | Bin 0 -> 586 bytes .../tzdata/zoneinfo/America/Mexico_City | Bin 0 -> 773 bytes .../tzdata/zoneinfo/America/Miquelon | Bin 0 -> 550 bytes .../tzdata/zoneinfo/America/Moncton | Bin 0 -> 1493 bytes .../tzdata/zoneinfo/America/Monterrey | Bin 0 -> 709 bytes .../tzdata/zoneinfo/America/Montevideo | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Montreal | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Montserrat | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Nassau | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/New_York | Bin 0 -> 1744 bytes .../tzdata/zoneinfo/America/Nipigon | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Nome | Bin 0 -> 975 bytes .../tzdata/zoneinfo/America/Noronha | Bin 0 -> 484 bytes .../zoneinfo/America/North_Dakota/Beulah | Bin 0 -> 1043 bytes .../zoneinfo/America/North_Dakota/Center | Bin 0 -> 990 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 0 -> 990 bytes .../zoneinfo/America/North_Dakota/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 216 bytes .../tzdata/zoneinfo/America/Nuuk | Bin 0 -> 965 bytes .../tzdata/zoneinfo/America/Ojinaga | Bin 0 -> 718 bytes .../tzdata/zoneinfo/America/Panama | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Pangnirtung | Bin 0 -> 855 bytes .../tzdata/zoneinfo/America/Paramaribo | Bin 0 -> 187 bytes .../tzdata/zoneinfo/America/Phoenix | Bin 0 -> 240 bytes .../tzdata/zoneinfo/America/Port-au-Prince | Bin 0 -> 565 bytes .../tzdata/zoneinfo/America/Port_of_Spain | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Porto_Acre | Bin 0 -> 418 bytes .../tzdata/zoneinfo/America/Porto_Velho | Bin 0 -> 394 bytes .../tzdata/zoneinfo/America/Puerto_Rico | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Punta_Arenas | Bin 0 -> 1218 bytes .../tzdata/zoneinfo/America/Rainy_River | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Rankin_Inlet | Bin 0 -> 807 bytes .../tzdata/zoneinfo/America/Recife | Bin 0 -> 484 bytes .../tzdata/zoneinfo/America/Regina | Bin 0 -> 638 bytes .../tzdata/zoneinfo/America/Resolute | Bin 0 -> 807 bytes .../tzdata/zoneinfo/America/Rio_Branco | Bin 0 -> 418 bytes .../tzdata/zoneinfo/America/Rosario | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Santa_Isabel | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Santarem | Bin 0 -> 409 bytes .../tzdata/zoneinfo/America/Santiago | Bin 0 -> 1354 bytes .../tzdata/zoneinfo/America/Santo_Domingo | Bin 0 -> 317 bytes .../tzdata/zoneinfo/America/Sao_Paulo | Bin 0 -> 952 bytes .../tzdata/zoneinfo/America/Scoresbysund | Bin 0 -> 984 bytes .../tzdata/zoneinfo/America/Shiprock | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/America/Sitka | Bin 0 -> 956 bytes .../tzdata/zoneinfo/America/St_Barthelemy | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Johns | Bin 0 -> 1878 bytes .../tzdata/zoneinfo/America/St_Kitts | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Lucia | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Thomas | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Vincent | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Swift_Current | Bin 0 -> 368 bytes .../tzdata/zoneinfo/America/Tegucigalpa | Bin 0 -> 194 bytes .../tzdata/zoneinfo/America/Thule | Bin 0 -> 455 bytes .../tzdata/zoneinfo/America/Thunder_Bay | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Tijuana | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Toronto | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Tortola | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Vancouver | Bin 0 -> 1330 bytes .../tzdata/zoneinfo/America/Virgin | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Whitehorse | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/America/Winnipeg | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Yakutat | Bin 0 -> 946 bytes .../tzdata/zoneinfo/America/Yellowknife | Bin 0 -> 970 bytes .../tzdata/zoneinfo/America/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 203 bytes .../tzdata/zoneinfo/Antarctica/Casey | Bin 0 -> 287 bytes .../tzdata/zoneinfo/Antarctica/Davis | Bin 0 -> 197 bytes .../tzdata/zoneinfo/Antarctica/DumontDUrville | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Antarctica/Macquarie | Bin 0 -> 976 bytes .../tzdata/zoneinfo/Antarctica/Mawson | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Antarctica/McMurdo | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Antarctica/Palmer | Bin 0 -> 887 bytes .../tzdata/zoneinfo/Antarctica/Rothera | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Antarctica/South_Pole | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Antarctica/Syowa | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Antarctica/Troll | Bin 0 -> 158 bytes .../tzdata/zoneinfo/Antarctica/Vostok | Bin 0 -> 170 bytes .../tzdata/zoneinfo/Antarctica/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 206 bytes .../tzdata/zoneinfo/Arctic/Longyearbyen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Arctic/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes .../site-packages/tzdata/zoneinfo/Asia/Aden | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Almaty | Bin 0 -> 618 bytes .../site-packages/tzdata/zoneinfo/Asia/Amman | Bin 0 -> 928 bytes .../site-packages/tzdata/zoneinfo/Asia/Anadyr | Bin 0 -> 743 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtau | Bin 0 -> 606 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtobe | Bin 0 -> 615 bytes .../tzdata/zoneinfo/Asia/Ashgabat | Bin 0 -> 375 bytes .../tzdata/zoneinfo/Asia/Ashkhabad | Bin 0 -> 375 bytes .../site-packages/tzdata/zoneinfo/Asia/Atyrau | Bin 0 -> 616 bytes .../tzdata/zoneinfo/Asia/Baghdad | Bin 0 -> 630 bytes .../tzdata/zoneinfo/Asia/Bahrain | Bin 0 -> 152 bytes .../site-packages/tzdata/zoneinfo/Asia/Baku | Bin 0 -> 744 bytes .../tzdata/zoneinfo/Asia/Bangkok | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Barnaul | Bin 0 -> 753 bytes .../site-packages/tzdata/zoneinfo/Asia/Beirut | Bin 0 -> 732 bytes .../tzdata/zoneinfo/Asia/Bishkek | Bin 0 -> 618 bytes .../site-packages/tzdata/zoneinfo/Asia/Brunei | Bin 0 -> 320 bytes .../tzdata/zoneinfo/Asia/Calcutta | Bin 0 -> 220 bytes .../site-packages/tzdata/zoneinfo/Asia/Chita | Bin 0 -> 750 bytes .../tzdata/zoneinfo/Asia/Choibalsan | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Chongqing | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Chungking | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Colombo | Bin 0 -> 247 bytes .../site-packages/tzdata/zoneinfo/Asia/Dacca | Bin 0 -> 231 bytes .../tzdata/zoneinfo/Asia/Damascus | Bin 0 -> 1234 bytes .../site-packages/tzdata/zoneinfo/Asia/Dhaka | Bin 0 -> 231 bytes .../site-packages/tzdata/zoneinfo/Asia/Dili | Bin 0 -> 170 bytes .../site-packages/tzdata/zoneinfo/Asia/Dubai | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Dushanbe | Bin 0 -> 366 bytes .../tzdata/zoneinfo/Asia/Famagusta | Bin 0 -> 940 bytes .../site-packages/tzdata/zoneinfo/Asia/Gaza | Bin 0 -> 2950 bytes .../site-packages/tzdata/zoneinfo/Asia/Harbin | Bin 0 -> 393 bytes .../site-packages/tzdata/zoneinfo/Asia/Hebron | Bin 0 -> 2968 bytes .../tzdata/zoneinfo/Asia/Ho_Chi_Minh | Bin 0 -> 236 bytes .../tzdata/zoneinfo/Asia/Hong_Kong | Bin 0 -> 775 bytes .../site-packages/tzdata/zoneinfo/Asia/Hovd | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Irkutsk | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Asia/Istanbul | Bin 0 -> 1200 bytes .../tzdata/zoneinfo/Asia/Jakarta | Bin 0 -> 248 bytes .../tzdata/zoneinfo/Asia/Jayapura | Bin 0 -> 171 bytes .../tzdata/zoneinfo/Asia/Jerusalem | Bin 0 -> 1074 bytes .../site-packages/tzdata/zoneinfo/Asia/Kabul | Bin 0 -> 159 bytes .../tzdata/zoneinfo/Asia/Kamchatka | Bin 0 -> 727 bytes .../tzdata/zoneinfo/Asia/Karachi | Bin 0 -> 266 bytes .../tzdata/zoneinfo/Asia/Kashgar | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Kathmandu | Bin 0 -> 161 bytes .../tzdata/zoneinfo/Asia/Katmandu | Bin 0 -> 161 bytes .../tzdata/zoneinfo/Asia/Khandyga | Bin 0 -> 775 bytes .../tzdata/zoneinfo/Asia/Kolkata | Bin 0 -> 220 bytes .../tzdata/zoneinfo/Asia/Krasnoyarsk | Bin 0 -> 741 bytes .../tzdata/zoneinfo/Asia/Kuala_Lumpur | Bin 0 -> 256 bytes .../tzdata/zoneinfo/Asia/Kuching | Bin 0 -> 320 bytes .../site-packages/tzdata/zoneinfo/Asia/Kuwait | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Macao | Bin 0 -> 791 bytes .../site-packages/tzdata/zoneinfo/Asia/Macau | Bin 0 -> 791 bytes .../tzdata/zoneinfo/Asia/Magadan | Bin 0 -> 751 bytes .../tzdata/zoneinfo/Asia/Makassar | Bin 0 -> 190 bytes .../site-packages/tzdata/zoneinfo/Asia/Manila | Bin 0 -> 274 bytes .../site-packages/tzdata/zoneinfo/Asia/Muscat | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Nicosia | Bin 0 -> 597 bytes .../tzdata/zoneinfo/Asia/Novokuznetsk | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Asia/Novosibirsk | Bin 0 -> 753 bytes .../site-packages/tzdata/zoneinfo/Asia/Omsk | Bin 0 -> 741 bytes .../site-packages/tzdata/zoneinfo/Asia/Oral | Bin 0 -> 625 bytes .../tzdata/zoneinfo/Asia/Phnom_Penh | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Pontianak | Bin 0 -> 247 bytes .../tzdata/zoneinfo/Asia/Pyongyang | Bin 0 -> 183 bytes .../site-packages/tzdata/zoneinfo/Asia/Qatar | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Qostanay | Bin 0 -> 624 bytes .../tzdata/zoneinfo/Asia/Qyzylorda | Bin 0 -> 624 bytes .../tzdata/zoneinfo/Asia/Rangoon | Bin 0 -> 187 bytes .../site-packages/tzdata/zoneinfo/Asia/Riyadh | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Saigon | Bin 0 -> 236 bytes .../tzdata/zoneinfo/Asia/Sakhalin | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Asia/Samarkand | Bin 0 -> 366 bytes .../site-packages/tzdata/zoneinfo/Asia/Seoul | Bin 0 -> 415 bytes .../tzdata/zoneinfo/Asia/Shanghai | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Singapore | Bin 0 -> 256 bytes .../tzdata/zoneinfo/Asia/Srednekolymsk | Bin 0 -> 742 bytes .../site-packages/tzdata/zoneinfo/Asia/Taipei | Bin 0 -> 511 bytes .../tzdata/zoneinfo/Asia/Tashkent | Bin 0 -> 366 bytes .../tzdata/zoneinfo/Asia/Tbilisi | Bin 0 -> 629 bytes .../site-packages/tzdata/zoneinfo/Asia/Tehran | Bin 0 -> 812 bytes .../tzdata/zoneinfo/Asia/Tel_Aviv | Bin 0 -> 1074 bytes .../site-packages/tzdata/zoneinfo/Asia/Thimbu | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Asia/Thimphu | Bin 0 -> 154 bytes .../site-packages/tzdata/zoneinfo/Asia/Tokyo | Bin 0 -> 213 bytes .../site-packages/tzdata/zoneinfo/Asia/Tomsk | Bin 0 -> 753 bytes .../tzdata/zoneinfo/Asia/Ujung_Pandang | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Asia/Ulaanbaatar | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Ulan_Bator | Bin 0 -> 594 bytes .../site-packages/tzdata/zoneinfo/Asia/Urumqi | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Ust-Nera | Bin 0 -> 771 bytes .../tzdata/zoneinfo/Asia/Vientiane | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Vladivostok | Bin 0 -> 742 bytes .../tzdata/zoneinfo/Asia/Yakutsk | Bin 0 -> 741 bytes .../site-packages/tzdata/zoneinfo/Asia/Yangon | Bin 0 -> 187 bytes .../tzdata/zoneinfo/Asia/Yekaterinburg | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Asia/Yerevan | Bin 0 -> 708 bytes .../tzdata/zoneinfo/Asia/__init__.py | 0 .../Asia/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 200 bytes .../tzdata/zoneinfo/Atlantic/Azores | Bin 0 -> 1401 bytes .../tzdata/zoneinfo/Atlantic/Bermuda | Bin 0 -> 1024 bytes .../tzdata/zoneinfo/Atlantic/Canary | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Atlantic/Cape_Verde | Bin 0 -> 175 bytes .../tzdata/zoneinfo/Atlantic/Faeroe | Bin 0 -> 441 bytes .../tzdata/zoneinfo/Atlantic/Faroe | Bin 0 -> 441 bytes .../tzdata/zoneinfo/Atlantic/Jan_Mayen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Atlantic/Madeira | Bin 0 -> 1372 bytes .../tzdata/zoneinfo/Atlantic/Reykjavik | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Atlantic/South_Georgia | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Atlantic/St_Helena | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Atlantic/Stanley | Bin 0 -> 789 bytes .../tzdata/zoneinfo/Atlantic/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 204 bytes .../tzdata/zoneinfo/Australia/ACT | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Adelaide | Bin 0 -> 921 bytes .../tzdata/zoneinfo/Australia/Brisbane | Bin 0 -> 289 bytes .../tzdata/zoneinfo/Australia/Broken_Hill | Bin 0 -> 941 bytes .../tzdata/zoneinfo/Australia/Canberra | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Currie | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/Darwin | Bin 0 -> 234 bytes .../tzdata/zoneinfo/Australia/Eucla | Bin 0 -> 314 bytes .../tzdata/zoneinfo/Australia/Hobart | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/LHI | Bin 0 -> 692 bytes .../tzdata/zoneinfo/Australia/Lindeman | Bin 0 -> 325 bytes .../tzdata/zoneinfo/Australia/Lord_Howe | Bin 0 -> 692 bytes .../tzdata/zoneinfo/Australia/Melbourne | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/NSW | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/North | Bin 0 -> 234 bytes .../tzdata/zoneinfo/Australia/Perth | Bin 0 -> 306 bytes .../tzdata/zoneinfo/Australia/Queensland | Bin 0 -> 289 bytes .../tzdata/zoneinfo/Australia/South | Bin 0 -> 921 bytes .../tzdata/zoneinfo/Australia/Sydney | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Tasmania | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/Victoria | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/West | Bin 0 -> 306 bytes .../tzdata/zoneinfo/Australia/Yancowinna | Bin 0 -> 941 bytes .../tzdata/zoneinfo/Australia/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 205 bytes .../site-packages/tzdata/zoneinfo/Brazil/Acre | Bin 0 -> 418 bytes .../tzdata/zoneinfo/Brazil/DeNoronha | Bin 0 -> 484 bytes .../site-packages/tzdata/zoneinfo/Brazil/East | Bin 0 -> 952 bytes .../site-packages/tzdata/zoneinfo/Brazil/West | Bin 0 -> 412 bytes .../tzdata/zoneinfo/Brazil/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes venv/Lib/site-packages/tzdata/zoneinfo/CET | Bin 0 -> 1103 bytes .../Lib/site-packages/tzdata/zoneinfo/CST6CDT | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/Canada/Atlantic | Bin 0 -> 1672 bytes .../tzdata/zoneinfo/Canada/Central | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/Canada/Eastern | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/Canada/Mountain | Bin 0 -> 970 bytes .../tzdata/zoneinfo/Canada/Newfoundland | Bin 0 -> 1878 bytes .../tzdata/zoneinfo/Canada/Pacific | Bin 0 -> 1330 bytes .../tzdata/zoneinfo/Canada/Saskatchewan | Bin 0 -> 638 bytes .../tzdata/zoneinfo/Canada/Yukon | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/Canada/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes .../tzdata/zoneinfo/Chile/Continental | Bin 0 -> 1354 bytes .../tzdata/zoneinfo/Chile/EasterIsland | Bin 0 -> 1174 bytes .../tzdata/zoneinfo/Chile/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 201 bytes venv/Lib/site-packages/tzdata/zoneinfo/Cuba | Bin 0 -> 1117 bytes venv/Lib/site-packages/tzdata/zoneinfo/EET | Bin 0 -> 682 bytes venv/Lib/site-packages/tzdata/zoneinfo/EST | Bin 0 -> 149 bytes .../Lib/site-packages/tzdata/zoneinfo/EST5EDT | Bin 0 -> 1744 bytes venv/Lib/site-packages/tzdata/zoneinfo/Egypt | Bin 0 -> 1309 bytes venv/Lib/site-packages/tzdata/zoneinfo/Eire | Bin 0 -> 1496 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/GMT | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+1 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+10 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+11 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+12 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+2 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+3 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+4 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+5 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+6 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+7 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+8 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+9 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-1 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-10 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-11 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-12 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-13 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-14 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-2 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-3 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-4 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-5 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-6 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-7 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-8 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-9 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT0 | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/Greenwich | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UCT | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UTC | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/Universal | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/Zulu | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/__init__.py | 0 .../Etc/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 199 bytes .../tzdata/zoneinfo/Europe/Amsterdam | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Andorra | Bin 0 -> 389 bytes .../tzdata/zoneinfo/Europe/Astrakhan | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Europe/Athens | Bin 0 -> 682 bytes .../tzdata/zoneinfo/Europe/Belfast | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Belgrade | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Berlin | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Bratislava | Bin 0 -> 723 bytes .../tzdata/zoneinfo/Europe/Brussels | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Bucharest | Bin 0 -> 661 bytes .../tzdata/zoneinfo/Europe/Budapest | Bin 0 -> 766 bytes .../tzdata/zoneinfo/Europe/Busingen | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/Chisinau | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Europe/Copenhagen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Dublin | Bin 0 -> 1496 bytes .../tzdata/zoneinfo/Europe/Gibraltar | Bin 0 -> 1220 bytes .../tzdata/zoneinfo/Europe/Guernsey | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Helsinki | Bin 0 -> 481 bytes .../tzdata/zoneinfo/Europe/Isle_of_Man | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Istanbul | Bin 0 -> 1200 bytes .../tzdata/zoneinfo/Europe/Jersey | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Kaliningrad | Bin 0 -> 904 bytes .../site-packages/tzdata/zoneinfo/Europe/Kiev | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Kirov | Bin 0 -> 735 bytes .../site-packages/tzdata/zoneinfo/Europe/Kyiv | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Lisbon | Bin 0 -> 1463 bytes .../tzdata/zoneinfo/Europe/Ljubljana | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/London | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Luxembourg | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Madrid | Bin 0 -> 897 bytes .../tzdata/zoneinfo/Europe/Malta | Bin 0 -> 928 bytes .../tzdata/zoneinfo/Europe/Mariehamn | Bin 0 -> 481 bytes .../tzdata/zoneinfo/Europe/Minsk | Bin 0 -> 808 bytes .../tzdata/zoneinfo/Europe/Monaco | Bin 0 -> 1105 bytes .../tzdata/zoneinfo/Europe/Moscow | Bin 0 -> 908 bytes .../tzdata/zoneinfo/Europe/Nicosia | Bin 0 -> 597 bytes .../site-packages/tzdata/zoneinfo/Europe/Oslo | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Paris | Bin 0 -> 1105 bytes .../tzdata/zoneinfo/Europe/Podgorica | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Prague | Bin 0 -> 723 bytes .../site-packages/tzdata/zoneinfo/Europe/Riga | Bin 0 -> 694 bytes .../site-packages/tzdata/zoneinfo/Europe/Rome | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Samara | Bin 0 -> 732 bytes .../tzdata/zoneinfo/Europe/San_Marino | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Sarajevo | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Saratov | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Europe/Simferopol | Bin 0 -> 865 bytes .../tzdata/zoneinfo/Europe/Skopje | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Sofia | Bin 0 -> 592 bytes .../tzdata/zoneinfo/Europe/Stockholm | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Tallinn | Bin 0 -> 675 bytes .../tzdata/zoneinfo/Europe/Tirane | Bin 0 -> 604 bytes .../tzdata/zoneinfo/Europe/Tiraspol | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Europe/Ulyanovsk | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Europe/Uzhgorod | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Vaduz | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/Vatican | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Vienna | Bin 0 -> 658 bytes .../tzdata/zoneinfo/Europe/Vilnius | Bin 0 -> 676 bytes .../tzdata/zoneinfo/Europe/Volgograd | Bin 0 -> 753 bytes .../tzdata/zoneinfo/Europe/Warsaw | Bin 0 -> 923 bytes .../tzdata/zoneinfo/Europe/Zagreb | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Zaporozhye | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Zurich | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes .../Lib/site-packages/tzdata/zoneinfo/Factory | Bin 0 -> 113 bytes venv/Lib/site-packages/tzdata/zoneinfo/GB | Bin 0 -> 1599 bytes .../Lib/site-packages/tzdata/zoneinfo/GB-Eire | Bin 0 -> 1599 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT | Bin 0 -> 111 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT+0 | Bin 0 -> 111 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT-0 | Bin 0 -> 111 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Greenwich | Bin 0 -> 111 bytes venv/Lib/site-packages/tzdata/zoneinfo/HST | Bin 0 -> 221 bytes .../site-packages/tzdata/zoneinfo/Hongkong | Bin 0 -> 775 bytes .../Lib/site-packages/tzdata/zoneinfo/Iceland | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Indian/Antananarivo | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Chagos | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Christmas | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Cocos | Bin 0 -> 187 bytes .../tzdata/zoneinfo/Indian/Comoro | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Kerguelen | Bin 0 -> 152 bytes .../site-packages/tzdata/zoneinfo/Indian/Mahe | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Indian/Maldives | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Mauritius | Bin 0 -> 179 bytes .../tzdata/zoneinfo/Indian/Mayotte | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Reunion | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Indian/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes venv/Lib/site-packages/tzdata/zoneinfo/Iran | Bin 0 -> 812 bytes venv/Lib/site-packages/tzdata/zoneinfo/Israel | Bin 0 -> 1074 bytes .../Lib/site-packages/tzdata/zoneinfo/Jamaica | Bin 0 -> 339 bytes venv/Lib/site-packages/tzdata/zoneinfo/Japan | Bin 0 -> 213 bytes .../site-packages/tzdata/zoneinfo/Kwajalein | Bin 0 -> 219 bytes venv/Lib/site-packages/tzdata/zoneinfo/Libya | Bin 0 -> 431 bytes venv/Lib/site-packages/tzdata/zoneinfo/MET | Bin 0 -> 1103 bytes venv/Lib/site-packages/tzdata/zoneinfo/MST | Bin 0 -> 240 bytes .../Lib/site-packages/tzdata/zoneinfo/MST7MDT | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/Mexico/BajaNorte | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/Mexico/BajaSur | Bin 0 -> 690 bytes .../tzdata/zoneinfo/Mexico/General | Bin 0 -> 773 bytes .../tzdata/zoneinfo/Mexico/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes venv/Lib/site-packages/tzdata/zoneinfo/NZ | Bin 0 -> 1043 bytes .../Lib/site-packages/tzdata/zoneinfo/NZ-CHAT | Bin 0 -> 808 bytes venv/Lib/site-packages/tzdata/zoneinfo/Navajo | Bin 0 -> 1042 bytes venv/Lib/site-packages/tzdata/zoneinfo/PRC | Bin 0 -> 393 bytes .../Lib/site-packages/tzdata/zoneinfo/PST8PDT | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/Pacific/Apia | Bin 0 -> 407 bytes .../tzdata/zoneinfo/Pacific/Auckland | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Pacific/Bougainville | Bin 0 -> 201 bytes .../tzdata/zoneinfo/Pacific/Chatham | Bin 0 -> 808 bytes .../tzdata/zoneinfo/Pacific/Chuuk | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Easter | Bin 0 -> 1174 bytes .../tzdata/zoneinfo/Pacific/Efate | Bin 0 -> 342 bytes .../tzdata/zoneinfo/Pacific/Enderbury | Bin 0 -> 172 bytes .../tzdata/zoneinfo/Pacific/Fakaofo | Bin 0 -> 153 bytes .../tzdata/zoneinfo/Pacific/Fiji | Bin 0 -> 396 bytes .../tzdata/zoneinfo/Pacific/Funafuti | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Galapagos | Bin 0 -> 175 bytes .../tzdata/zoneinfo/Pacific/Gambier | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Pacific/Guadalcanal | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Guam | Bin 0 -> 350 bytes .../tzdata/zoneinfo/Pacific/Honolulu | Bin 0 -> 221 bytes .../tzdata/zoneinfo/Pacific/Johnston | Bin 0 -> 221 bytes .../tzdata/zoneinfo/Pacific/Kanton | Bin 0 -> 172 bytes .../tzdata/zoneinfo/Pacific/Kiritimati | Bin 0 -> 174 bytes .../tzdata/zoneinfo/Pacific/Kosrae | Bin 0 -> 242 bytes .../tzdata/zoneinfo/Pacific/Kwajalein | Bin 0 -> 219 bytes .../tzdata/zoneinfo/Pacific/Majuro | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Marquesas | Bin 0 -> 139 bytes .../tzdata/zoneinfo/Pacific/Midway | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Nauru | Bin 0 -> 183 bytes .../tzdata/zoneinfo/Pacific/Niue | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Norfolk | Bin 0 -> 237 bytes .../tzdata/zoneinfo/Pacific/Noumea | Bin 0 -> 198 bytes .../tzdata/zoneinfo/Pacific/Pago_Pago | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Palau | Bin 0 -> 148 bytes .../tzdata/zoneinfo/Pacific/Pitcairn | Bin 0 -> 153 bytes .../tzdata/zoneinfo/Pacific/Pohnpei | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Ponape | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Port_Moresby | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Rarotonga | Bin 0 -> 406 bytes .../tzdata/zoneinfo/Pacific/Saipan | Bin 0 -> 350 bytes .../tzdata/zoneinfo/Pacific/Samoa | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Tahiti | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Pacific/Tarawa | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Tongatapu | Bin 0 -> 237 bytes .../tzdata/zoneinfo/Pacific/Truk | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Wake | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Wallis | Bin 0 -> 134 bytes .../site-packages/tzdata/zoneinfo/Pacific/Yap | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 203 bytes venv/Lib/site-packages/tzdata/zoneinfo/Poland | Bin 0 -> 923 bytes .../site-packages/tzdata/zoneinfo/Portugal | Bin 0 -> 1463 bytes venv/Lib/site-packages/tzdata/zoneinfo/ROC | Bin 0 -> 511 bytes venv/Lib/site-packages/tzdata/zoneinfo/ROK | Bin 0 -> 415 bytes .../site-packages/tzdata/zoneinfo/Singapore | Bin 0 -> 256 bytes venv/Lib/site-packages/tzdata/zoneinfo/Turkey | Bin 0 -> 1200 bytes venv/Lib/site-packages/tzdata/zoneinfo/UCT | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/US/Alaska | Bin 0 -> 977 bytes .../site-packages/tzdata/zoneinfo/US/Aleutian | Bin 0 -> 969 bytes .../site-packages/tzdata/zoneinfo/US/Arizona | Bin 0 -> 240 bytes .../site-packages/tzdata/zoneinfo/US/Central | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/US/East-Indiana | Bin 0 -> 531 bytes .../site-packages/tzdata/zoneinfo/US/Eastern | Bin 0 -> 1744 bytes .../site-packages/tzdata/zoneinfo/US/Hawaii | Bin 0 -> 221 bytes .../tzdata/zoneinfo/US/Indiana-Starke | Bin 0 -> 1016 bytes .../site-packages/tzdata/zoneinfo/US/Michigan | Bin 0 -> 899 bytes .../site-packages/tzdata/zoneinfo/US/Mountain | Bin 0 -> 1042 bytes .../site-packages/tzdata/zoneinfo/US/Pacific | Bin 0 -> 1294 bytes .../site-packages/tzdata/zoneinfo/US/Samoa | Bin 0 -> 146 bytes .../tzdata/zoneinfo/US/__init__.py | 0 .../US/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 198 bytes venv/Lib/site-packages/tzdata/zoneinfo/UTC | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Universal | Bin 0 -> 111 bytes venv/Lib/site-packages/tzdata/zoneinfo/W-SU | Bin 0 -> 908 bytes venv/Lib/site-packages/tzdata/zoneinfo/WET | Bin 0 -> 1463 bytes venv/Lib/site-packages/tzdata/zoneinfo/Zulu | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 195 bytes .../site-packages/tzdata/zoneinfo/iso3166.tab | 279 + .../site-packages/tzdata/zoneinfo/leapseconds | 79 + .../site-packages/tzdata/zoneinfo/tzdata.zi | 4300 +++++++++ .../site-packages/tzdata/zoneinfo/zone.tab | 448 + .../tzdata/zoneinfo/zone1970.tab | 375 + .../site-packages/tzdata/zoneinfo/zonenow.tab | 296 + venv/Lib/site-packages/tzdata/zones | 598 ++ venv/Scripts/Activate.ps1 | 528 + venv/Scripts/activate | 71 + venv/Scripts/activate.bat | 34 + venv/Scripts/deactivate.bat | 22 + venv/Scripts/pip.exe | Bin 0 -> 108428 bytes venv/Scripts/pip3.12.exe | Bin 0 -> 108428 bytes venv/Scripts/pip3.exe | Bin 0 -> 108428 bytes venv/Scripts/python.exe | Bin 0 -> 275176 bytes venv/Scripts/pythonw.exe | Bin 0 -> 263528 bytes venv/Scripts/sqlformat.exe | Bin 0 -> 108423 bytes venv/app.py | 511 + venv/bufftech.xlsx | Bin 0 -> 493795 bytes venv/my_project_data.db | Bin 0 -> 221184 bytes venv/pyvenv.cfg | 5 + 2000 files changed, 183840 insertions(+) create mode 100644 Buff.xlsx create mode 100644 check_db.py create mode 100644 my_project_data.db create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/LICENSE create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/METADATA create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/RECORD create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/asgiref-3.8.1.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/asgiref/__init__.py create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/compatibility.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/current_thread_executor.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/local.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/server.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/sync.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/testing.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/timeout.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/typing.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/__pycache__/wsgi.cpython-312.pyc create mode 100644 venv/Lib/site-packages/asgiref/compatibility.py create mode 100644 venv/Lib/site-packages/asgiref/current_thread_executor.py create mode 100644 venv/Lib/site-packages/asgiref/local.py create mode 100644 venv/Lib/site-packages/asgiref/py.typed create mode 100644 venv/Lib/site-packages/asgiref/server.py create mode 100644 venv/Lib/site-packages/asgiref/sync.py create mode 100644 venv/Lib/site-packages/asgiref/testing.py create mode 100644 venv/Lib/site-packages/asgiref/timeout.py create mode 100644 venv/Lib/site-packages/asgiref/typing.py create mode 100644 venv/Lib/site-packages/asgiref/wsgi.py create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/AUTHORS.txt create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.python create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.rst create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/METADATA create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/RECORD create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/et_xmlfile/__init__.py create mode 100644 venv/Lib/site-packages/et_xmlfile/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/et_xmlfile/__pycache__/incremental_tree.cpython-312.pyc create mode 100644 venv/Lib/site-packages/et_xmlfile/__pycache__/xmlfile.cpython-312.pyc create mode 100644 venv/Lib/site-packages/et_xmlfile/incremental_tree.py create mode 100644 venv/Lib/site-packages/et_xmlfile/xmlfile.py create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/LICENCE.rst create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/METADATA create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/RECORD create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/REQUESTED create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/openpyxl-3.1.5.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/openpyxl/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/__pycache__/_constants.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/_constants.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/_writer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/cell.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/read_only.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/rich_text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/__pycache__/text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/cell/_writer.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/cell.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/read_only.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/rich_text.py create mode 100644 venv/Lib/site-packages/openpyxl/cell/text.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/_3d.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/_3d.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/area_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/axis.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/bar_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/bubble_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/chartspace.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/data_source.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/descriptors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/error_bar.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/label.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/layout.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/legend.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/line_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/marker.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/picture.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/pie_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/pivot.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/plotarea.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/print_settings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/radar_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/reader.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/reference.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/scatter_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/series.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/series_factory.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/shapes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/stock_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/surface_chart.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/title.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/trendline.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/__pycache__/updown_bars.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chart/_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/area_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/axis.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/bar_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/bubble_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/chartspace.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/data_source.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/descriptors.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/error_bar.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/label.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/layout.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/legend.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/line_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/marker.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/picture.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/pie_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/pivot.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/plotarea.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/print_settings.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/radar_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/reader.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/reference.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/scatter_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/series.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/series_factory.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/shapes.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/stock_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/surface_chart.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/text.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/title.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/trendline.py create mode 100644 venv/Lib/site-packages/openpyxl/chart/updown_bars.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/chartsheet.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/custom.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/properties.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/protection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/publish.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/relation.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/views.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/chartsheet.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/custom.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/properties.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/protection.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/publish.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/relation.py create mode 100644 venv/Lib/site-packages/openpyxl/chartsheet/views.py create mode 100644 venv/Lib/site-packages/openpyxl/comments/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/comments/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/comments/__pycache__/author.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/comments/__pycache__/comment_sheet.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/comments/__pycache__/comments.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/comments/__pycache__/shape_writer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/comments/author.py create mode 100644 venv/Lib/site-packages/openpyxl/comments/comment_sheet.py create mode 100644 venv/Lib/site-packages/openpyxl/comments/comments.py create mode 100644 venv/Lib/site-packages/openpyxl/comments/shape_writer.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/abc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/numbers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/product.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/singleton.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/__pycache__/strings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/compat/abc.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/numbers.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/product.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/singleton.py create mode 100644 venv/Lib/site-packages/openpyxl/compat/strings.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/container.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/excel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/namespace.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/nested.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/sequence.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/serialisable.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/__pycache__/slots.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/base.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/container.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/excel.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/namespace.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/nested.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/sequence.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/serialisable.py create mode 100644 venv/Lib/site-packages/openpyxl/descriptors/slots.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/colors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/connector.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/drawing.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/effect.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/fill.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/geometry.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/graphic.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/image.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/line.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/picture.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/properties.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/relation.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/spreadsheet_drawing.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/__pycache__/xdr.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/drawing/colors.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/connector.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/drawing.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/effect.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/fill.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/geometry.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/graphic.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/image.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/line.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/picture.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/properties.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/relation.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/spreadsheet_drawing.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/text.py create mode 100644 venv/Lib/site-packages/openpyxl/drawing/xdr.py create mode 100644 venv/Lib/site-packages/openpyxl/formatting/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/formatting/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formatting/__pycache__/formatting.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formatting/__pycache__/rule.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formatting/formatting.py create mode 100644 venv/Lib/site-packages/openpyxl/formatting/rule.py create mode 100644 venv/Lib/site-packages/openpyxl/formula/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/formula/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formula/__pycache__/tokenizer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formula/__pycache__/translate.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/formula/tokenizer.py create mode 100644 venv/Lib/site-packages/openpyxl/formula/translate.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/core.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/custom.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/extended.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/interface.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/manifest.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/relationship.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/__pycache__/workbook.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/packaging/core.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/custom.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/extended.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/interface.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/manifest.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/relationship.py create mode 100644 venv/Lib/site-packages/openpyxl/packaging/workbook.py create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__pycache__/cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__pycache__/fields.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__pycache__/record.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/pivot/__pycache__/table.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/pivot/cache.py create mode 100644 venv/Lib/site-packages/openpyxl/pivot/fields.py create mode 100644 venv/Lib/site-packages/openpyxl/pivot/record.py create mode 100644 venv/Lib/site-packages/openpyxl/pivot/table.py create mode 100644 venv/Lib/site-packages/openpyxl/reader/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/reader/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/reader/__pycache__/drawings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/reader/__pycache__/excel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/reader/__pycache__/strings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/reader/__pycache__/workbook.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/reader/drawings.py create mode 100644 venv/Lib/site-packages/openpyxl/reader/excel.py create mode 100644 venv/Lib/site-packages/openpyxl/reader/strings.py create mode 100644 venv/Lib/site-packages/openpyxl/reader/workbook.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/alignment.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/borders.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/builtins.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/cell_style.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/colors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/differential.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/fills.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/fonts.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/named_styles.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/numbers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/protection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/proxy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/styleable.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/stylesheet.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/__pycache__/table.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/styles/alignment.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/borders.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/builtins.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/cell_style.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/colors.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/differential.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/fills.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/fonts.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/named_styles.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/numbers.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/protection.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/proxy.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/styleable.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/stylesheet.py create mode 100644 venv/Lib/site-packages/openpyxl/styles/table.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/bound_dictionary.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/cell.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/dataframe.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/datetime.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/escape.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/formulas.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/indexed_list.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/inference.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/protection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/__pycache__/units.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/utils/bound_dictionary.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/cell.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/dataframe.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/datetime.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/escape.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/exceptions.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/formulas.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/indexed_list.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/inference.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/protection.py create mode 100644 venv/Lib/site-packages/openpyxl/utils/units.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/_writer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/child.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/defined_name.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/external_reference.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/function_group.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/properties.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/protection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/smart_tags.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/views.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/web.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/__pycache__/workbook.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/_writer.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/child.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/defined_name.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/external_link/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/external_link/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/external_link/__pycache__/external.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/workbook/external_link/external.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/external_reference.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/function_group.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/properties.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/protection.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/smart_tags.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/views.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/web.py create mode 100644 venv/Lib/site-packages/openpyxl/workbook/workbook.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/_read_only.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/_reader.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/_write_only.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/_writer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/cell_range.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/cell_watch.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/controls.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/copier.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/custom.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/datavalidation.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/dimensions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/drawing.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/errors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/filters.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/formula.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/header_footer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/hyperlink.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/merge.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/ole.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/page.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/pagebreak.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/picture.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/print_settings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/properties.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/protection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/related.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/scenario.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/smart_tag.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/table.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/views.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/__pycache__/worksheet.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/_read_only.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/_reader.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/_write_only.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/_writer.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/cell_range.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/cell_watch.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/controls.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/copier.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/custom.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/datavalidation.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/dimensions.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/drawing.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/errors.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/filters.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/formula.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/header_footer.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/hyperlink.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/merge.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/ole.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/page.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/pagebreak.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/picture.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/print_settings.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/properties.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/protection.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/related.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/scenario.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/smart_tag.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/table.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/views.py create mode 100644 venv/Lib/site-packages/openpyxl/worksheet/worksheet.py create mode 100644 venv/Lib/site-packages/openpyxl/writer/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/writer/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/writer/__pycache__/excel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/writer/__pycache__/theme.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/writer/excel.py create mode 100644 venv/Lib/site-packages/openpyxl/writer/theme.py create mode 100644 venv/Lib/site-packages/openpyxl/xml/__init__.py create mode 100644 venv/Lib/site-packages/openpyxl/xml/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/xml/__pycache__/constants.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/xml/__pycache__/functions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/openpyxl/xml/constants.py create mode 100644 venv/Lib/site-packages/openpyxl/xml/functions.py create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/pip/__init__.py create mode 100644 venv/Lib/site-packages/pip/__main__.py create mode 100644 venv/Lib/site-packages/pip/__pip-runner__.py create mode 100644 venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/build_env.py create mode 100644 venv/Lib/site-packages/pip/_internal/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/command_context.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/index_command.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/main.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/req_command.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/spinners.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/debug.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/index.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/inspect.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/configuration.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/installed.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/sdist.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/collector.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/package_finder.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/sources.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/_distutils.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/main.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/_json.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/direct_url.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/index.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/installation_report.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/link.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/scheme.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/search_scope.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/target_python.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/auth.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/download.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/session.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/utils.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 venv/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 venv/Lib/site-packages/pip/_internal/self_outdated_check.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/_log.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/datetime.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/egg_link.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/filetypes.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/retry.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/subprocess.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/unpacking.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/urls.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 venv/Lib/site-packages/pip/_internal/wheel_builder.py create mode 100644 venv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/distro.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_elffile.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_parser.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/metadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/tags.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/console.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/style.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/token.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_export_format.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_extension.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_fileno.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_loop.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_null_file.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_pick.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_stack.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_timer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/abc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/align.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/ansi.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/bar.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/box.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/cells.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/columns.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/console.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/constrain.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/containers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/control.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/emoji.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/errors.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/filesize.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/json.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/layout.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live_render.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/logging.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/markup.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/measure.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/padding.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pager.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/palette.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/panel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pretty.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/prompt.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/protocol.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/region.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/repr.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/rule.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/scope.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/screen.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/segment.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/spinner.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/status.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/style.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/styled.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/syntax.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/table.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/text.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/theme.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/themes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/traceback.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/tree.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_re.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_types.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_macos.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/typing_extensions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 venv/Lib/site-packages/pip/_vendor/vendor.txt create mode 100644 venv/Lib/site-packages/pip/py.typed create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/METADATA create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/RECORD create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/licenses/AUTHORS create mode 100644 venv/Lib/site-packages/sqlparse-0.5.3.dist-info/licenses/LICENSE create mode 100644 venv/Lib/site-packages/sqlparse/__init__.py create mode 100644 venv/Lib/site-packages/sqlparse/__main__.py create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/cli.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/formatter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/keywords.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/lexer.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/sql.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/tokens.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/__pycache__/utils.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/cli.py create mode 100644 venv/Lib/site-packages/sqlparse/engine/__init__.py create mode 100644 venv/Lib/site-packages/sqlparse/engine/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/engine/__pycache__/filter_stack.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/engine/__pycache__/grouping.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/engine/__pycache__/statement_splitter.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/engine/filter_stack.py create mode 100644 venv/Lib/site-packages/sqlparse/engine/grouping.py create mode 100644 venv/Lib/site-packages/sqlparse/engine/statement_splitter.py create mode 100644 venv/Lib/site-packages/sqlparse/exceptions.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/__init__.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/aligned_indent.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/others.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/output.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/reindent.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/right_margin.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/__pycache__/tokens.cpython-312.pyc create mode 100644 venv/Lib/site-packages/sqlparse/filters/aligned_indent.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/others.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/output.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/reindent.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/right_margin.py create mode 100644 venv/Lib/site-packages/sqlparse/filters/tokens.py create mode 100644 venv/Lib/site-packages/sqlparse/formatter.py create mode 100644 venv/Lib/site-packages/sqlparse/keywords.py create mode 100644 venv/Lib/site-packages/sqlparse/lexer.py create mode 100644 venv/Lib/site-packages/sqlparse/sql.py create mode 100644 venv/Lib/site-packages/sqlparse/tokens.py create mode 100644 venv/Lib/site-packages/sqlparse/utils.py create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/METADATA create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/RECORD create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/LICENSE create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/licenses/LICENSE_APACHE create mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/tzdata/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Abidjan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Accra create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Addis_Ababa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Algiers create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmara create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmera create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bamako create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bangui create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Banjul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bissau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Blantyre create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Brazzaville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bujumbura create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Cairo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Casablanca create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ceuta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Conakry create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dakar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dar_es_Salaam create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Djibouti create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Douala create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/El_Aaiun create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Freetown create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Gaborone create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Harare create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Johannesburg create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Juba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kampala create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Khartoum create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kigali create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kinshasa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lagos create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Libreville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lome create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Luanda create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lubumbashi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lusaka create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Malabo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maputo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maseru create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mbabane create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mogadishu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Monrovia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nairobi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ndjamena create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Niamey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nouakchott create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ouagadougou create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Porto-Novo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Sao_Tome create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Timbuktu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tripoli create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tunis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Windhoek create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Adak create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Anchorage create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Anguilla create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Antigua create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Araguaina create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Buenos_Aires create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Catamarca create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/ComodRivadavia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Cordoba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Jujuy create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/La_Rioja create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Mendoza create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Rio_Gallegos create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Salta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Juan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Luis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Tucuman create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Ushuaia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Aruba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Asuncion create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Atikokan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Atka create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia_Banderas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Barbados create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Belem create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Belize create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Blanc-Sablon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Boa_Vista create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bogota create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Boise create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Buenos_Aires create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cambridge_Bay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Campo_Grande create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cancun create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Caracas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Catamarca create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cayenne create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cayman create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Chicago create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Chihuahua create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ciudad_Juarez create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Coral_Harbour create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cordoba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Costa_Rica create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Coyhaique create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Creston create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cuiaba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Curacao create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Danmarkshavn create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson_Creek create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Denver create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Detroit create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dominica create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Edmonton create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Eirunepe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/El_Salvador create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ensenada create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Nelson create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Wayne create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fortaleza create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Glace_Bay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Godthab create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Goose_Bay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Grand_Turk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Grenada create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guadeloupe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guatemala create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guayaquil create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guyana create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Halifax create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Havana create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Hermosillo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Indianapolis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Knox create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Marengo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Petersburg create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Tell_City create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vevay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vincennes create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Winamac create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indianapolis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Inuvik create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Iqaluit create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Jamaica create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Jujuy create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Juneau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Louisville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Monticello create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Knox_IN create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kralendijk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/La_Paz create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Lima create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Los_Angeles create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Louisville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Lower_Princes create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Maceio create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Managua create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Manaus create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Marigot create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Martinique create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Matamoros create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mazatlan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mendoza create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Menominee create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Merida create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Metlakatla create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mexico_City create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Miquelon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Moncton create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Monterrey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montevideo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montreal create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montserrat create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nassau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/New_York create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nipigon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nome create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Noronha create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Beulah create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Center create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/New_Salem create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nuuk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ojinaga create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Panama create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Pangnirtung create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Paramaribo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Phoenix create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Port-au-Prince create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Port_of_Spain create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Acre create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Velho create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Puerto_Rico create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Punta_Arenas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rainy_River create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rankin_Inlet create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Recife create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Regina create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Resolute create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rio_Branco create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rosario create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santa_Isabel create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santarem create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santiago create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santo_Domingo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Sao_Paulo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Scoresbysund create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Shiprock create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Sitka create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Barthelemy create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Johns create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Kitts create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Lucia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Thomas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Vincent create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Swift_Current create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tegucigalpa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Thule create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Thunder_Bay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tijuana create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Toronto create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tortola create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Vancouver create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Virgin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Whitehorse create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Winnipeg create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Yakutat create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Yellowknife create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Casey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Davis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/DumontDUrville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Macquarie create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Mawson create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/McMurdo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Palmer create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Rothera create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/South_Pole create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Syowa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Troll create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Vostok create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/Longyearbyen create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aden create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Almaty create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Amman create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Anadyr create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtobe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashgabat create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashkhabad create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Atyrau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baghdad create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bahrain create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baku create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bangkok create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Barnaul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Beirut create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bishkek create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Brunei create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Calcutta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chita create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Choibalsan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chongqing create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chungking create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Colombo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dacca create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Damascus create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dhaka create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dili create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dubai create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dushanbe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Famagusta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Gaza create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Harbin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hebron create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ho_Chi_Minh create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hong_Kong create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hovd create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Irkutsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Istanbul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jakarta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jayapura create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jerusalem create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kabul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kamchatka create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Karachi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kashgar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kathmandu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Katmandu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Khandyga create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kolkata create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Krasnoyarsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuala_Lumpur create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuching create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuwait create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macao create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Magadan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Makassar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Manila create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Muscat create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Nicosia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novokuznetsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novosibirsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Omsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Oral create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Phnom_Penh create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pontianak create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pyongyang create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qatar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qostanay create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qyzylorda create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Rangoon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Riyadh create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Saigon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Sakhalin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Samarkand create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Seoul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Shanghai create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Singapore create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Srednekolymsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Taipei create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tashkent create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tbilisi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tehran create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tel_Aviv create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimbu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimphu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tokyo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tomsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ujung_Pandang create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulaanbaatar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulan_Bator create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Urumqi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ust-Nera create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vientiane create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vladivostok create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yakutsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yangon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yekaterinburg create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yerevan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Azores create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Bermuda create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Canary create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Cape_Verde create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faeroe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faroe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Jan_Mayen create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Madeira create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Reykjavik create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/South_Georgia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/St_Helena create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Stanley create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/ACT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Adelaide create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Brisbane create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Broken_Hill create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Canberra create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Currie create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Darwin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Eucla create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Hobart create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/LHI create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lindeman create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lord_Howe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Melbourne create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/NSW create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/North create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Perth create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Queensland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/South create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Sydney create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Tasmania create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Victoria create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/West create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Yancowinna create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/Acre create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/DeNoronha create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/East create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/West create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/CET create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/CST6CDT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Atlantic create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Central create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Eastern create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Mountain create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Newfoundland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Pacific create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Saskatchewan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Yukon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/Continental create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/EasterIsland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Cuba create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EET create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EST create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EST5EDT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Egypt create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Eire create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+1 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+10 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+11 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+12 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+2 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+3 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+4 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+5 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+6 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+7 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+8 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+9 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-1 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-10 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-11 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-12 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-13 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-14 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-2 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-3 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-4 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-5 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-6 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-7 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-8 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-9 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Greenwich create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/UCT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/UTC create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Universal create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Zulu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Amsterdam create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Andorra create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Astrakhan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Athens create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belfast create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belgrade create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Berlin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bratislava create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Brussels create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bucharest create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Budapest create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Busingen create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Chisinau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Copenhagen create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Dublin create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Gibraltar create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Guernsey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Helsinki create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Isle_of_Man create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Istanbul create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Jersey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kaliningrad create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kiev create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kirov create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kyiv create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Lisbon create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ljubljana create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/London create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Luxembourg create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Madrid create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Malta create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Mariehamn create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Minsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Monaco create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Moscow create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Nicosia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Oslo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Paris create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Podgorica create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Prague create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Riga create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Rome create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Samara create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/San_Marino create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sarajevo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Saratov create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Simferopol create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Skopje create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sofia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Stockholm create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tallinn create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tirane create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tiraspol create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ulyanovsk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Uzhgorod create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vaduz create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vatican create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vienna create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vilnius create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Volgograd create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Warsaw create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zagreb create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zaporozhye create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zurich create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Factory create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GB create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GB-Eire create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT+0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT-0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT0 create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Greenwich create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/HST create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Hongkong create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Iceland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Antananarivo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Chagos create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Christmas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Cocos create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Comoro create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Kerguelen create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mahe create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Maldives create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mauritius create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mayotte create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Reunion create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Iran create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Israel create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Jamaica create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Japan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Kwajalein create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Libya create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MET create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MST create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MST7MDT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaNorte create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaSur create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/General create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/NZ create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/NZ-CHAT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Navajo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/PRC create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/PST8PDT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Apia create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Auckland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Bougainville create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chatham create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chuuk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Easter create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Efate create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Enderbury create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fakaofo create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fiji create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Funafuti create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Galapagos create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Gambier create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guadalcanal create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guam create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Honolulu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Johnston create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kanton create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kiritimati create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kosrae create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kwajalein create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Majuro create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Marquesas create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Midway create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Nauru create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Niue create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Norfolk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Noumea create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pago_Pago create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Palau create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pitcairn create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pohnpei create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Ponape create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Port_Moresby create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Rarotonga create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Saipan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Samoa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tahiti create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tarawa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tongatapu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Truk create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wake create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wallis create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Yap create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Poland create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Portugal create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/ROC create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/ROK create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Singapore create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Turkey create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/UCT create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Alaska create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Aleutian create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Arizona create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Central create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/East-Indiana create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Eastern create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Hawaii create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Indiana-Starke create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Michigan create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Mountain create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Pacific create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Samoa create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/UTC create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Universal create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/W-SU create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/WET create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Zulu create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/__init__.py create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/iso3166.tab create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/leapseconds create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/tzdata.zi create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zone.tab create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zone1970.tab create mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zonenow.tab create mode 100644 venv/Lib/site-packages/tzdata/zones create mode 100644 venv/Scripts/Activate.ps1 create mode 100644 venv/Scripts/activate create mode 100644 venv/Scripts/activate.bat create mode 100644 venv/Scripts/deactivate.bat create mode 100644 venv/Scripts/pip.exe create mode 100644 venv/Scripts/pip3.12.exe create mode 100644 venv/Scripts/pip3.exe create mode 100644 venv/Scripts/python.exe create mode 100644 venv/Scripts/pythonw.exe create mode 100644 venv/Scripts/sqlformat.exe create mode 100644 venv/app.py create mode 100644 venv/bufftech.xlsx create mode 100644 venv/my_project_data.db create mode 100644 venv/pyvenv.cfg diff --git a/Buff.xlsx b/Buff.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2c7e30d8ee7f97cc2f1ff3b9fc1e8809004bb515 GIT binary patch literal 34373 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

BW1|~JZ`63e2U_%3-qMyt#@DRhZ8p;6? zB;?5+Dz7FH8)MF8R_P+SPvry-R<2V_BN82`kp}lIv1h^l~|I^yegq6ESEE4gM_Q8*w$@tt-kO2>Uy}A5qOGz1F%o?pr@R}Rt{K;b*HMlGI|s^28rq~O5C|DeVS`oibAmV;dJ+zZIf?^-=2p#yT#6j z!d}acb7bFJud=@|#nDG>!aqrcr_Azi4EVJtw9bAjl(Rx^@=R~$vWs8n=mWX=)shOs9wME=V*Jj=?FzGF<*LJL~FG)1G) zF@<41uNE-*mVrEDEcNU0mdVGHoC?IT^F?YWYDT6z>hp^h9K!aSh}=4e^>E7~kMLVp zl}anwR=Mt2p%O7K%I|)l zHo1U4`B}gfwgDbE) zUSmN3&Srj}y%!mZ!ONQ$93ua_KWv8Kt+%I;=oh?~Vvde1MkHXz0ymK(th9wVPOiMR z16X+-lJQ->q+G{L4iegb}bgKfEik`m=zH%2L|!lt*YQhf*@#t}&Druewv`|ekkU0&be_soj?9~cht zXUhc`NDIg~?ZIK~LKz4GaRITEUdNIV3-|GS7ZU-C4+u$>Q4#5)UVIu^1hxk2kztHO zRjBy!PU5fa=;&z$E>@k08m==&XD04shCt&27tTvh`7R|9*>GsTV!_QIw(D^hycer( zL=CsBb#}9%fjTnL(ldG2v@K0E`>9tR+ zpGr0nhP`s#J098~jWOIKBR8UYO13h=`={5x7Pr#55Cq@`;Y9VH zeySg{`q8}Y1`#N&C)Zsg)T2`b{tc9}BO&=!c?H*@m&Q6QU&~lY3}byiFQ#E45C}ql za9F=k#xsGqI6TVRlU+BNn2#OZSJMhHgw1DYF{W|LbamaBl@EIKePSO}8D+ne5G1gX zBmZ_9PChZLLz&p$-oMo2Sz5$BJWaKWqn%XPJf&vMtO^j>JWNB>Eg*xc`dgEN$3Rua z*`&QW5wP^axKjsn*=~Ws*unYz+t|&Bg^3cynYm(GNfu#qlg|_T&$wb_;~MinpWGp0 z6Q)rUi_>11N2YjX_H}jY79^*>df8y<`ju2Ww{M6ucr#sxwGTwlOCugb(11=6&rTfg z)RTZm2<3e%4uf@{us92-)of2Vu@Q~Vex%NK4*1}V$NN@;?d?`nlpTe%1PJK;^FLsA zH;x`zjgt0JCIhocFWIybTU5flfGgqfJwq&xDipbU0`%%kt%wY2 zEKQ zRVdWZ1KOG6ddrA1Rk?BEtky?M*A5Hl0S>oMM_&d0Rf#u!VdPKLsQtnmPrul~^+H2- zZVlnGbPs`|ik-MBGU~S-oiQyZY%p>i)yt>dTXR8$uyfeWHKSO2VQc+W`DI$cGQX5p z_BE$k7w5}OFuj0My|JUdo@m(&G@_tcrh%87&Z(L zg6rNp7iZsLCcT7M%8w0`HIi$UUXWivSh~^ZN8uqMd#2{{>TSv3$Tc}dAt$!Fx?z`B z=96xEy#lhdSD4O(2a>&v3ELa)?tLujHIt-My%fuOgla$_#uC}OJw+m-kf2iJHx7>a zi;`snFs4DU_d^`%04EiRt;;H#MQHT!gbZ<&)7$ocouu3&ZuH_YA8Cz6Y%JGY(Ivi! zHr24L@PhD&m=o@NR958eB@gW+V~(Y2>QX9W^UsYx_4rc@h5x3wUX8v!p#&pPRGq6r0}H*xR^xK7Nf?sff&+%}CxRH-WK8hC(Zl;aQX8IWZNc}@stdfk-9YVQhjdY$^@ z+xR55w{`Krdm!Q1KK1onW%U~Sc9l*2Tl%~?`}^giroZ-SEOcCfBM-C8fK2u~yYGjs zZ(|RlZ->+UurOV99=)sBTHo#N7M4J?i}kwqQWrQ7`Tk3^lSIQPd!l zM}=xTYtLqcjK>#rjID2Z#l*j0K_%ie7r|wt&E%Q$#^WvJ@wK9i3wO=JwK7CDHIR{@41Lw=Y^^jKyM-LiN~A{N zg^>UcXH#!?)37>MfpG4>UcN?v$a$WrvSz{|sHRa!goUhUV&Y6lepBB|dYCf<)vci! ziBBsbe#;4R#p5;8U^62nSCLY5B_zMC?1Wf`Zp zEkd)0FSuVG56(XlH;TMCbiVFRHZb?<)+Z)u#G;aky|g(-;(@$NW(%wYTX@xSacz;V zA3z_YQ@^_&!yb=V3l^j89qCkrq0>34_zm*OQc%%9xF<$_L=BY1Z__{P#29r3+#M_y zMe++b%_Jez1>DpgZ&nx?Z>;D^A3WpQl#K(kVp6B~1N|9AtX@JFaM5urF=9+8M^Ydz z3s2#%6ciMUQC(O+B&RkI_I!l=8dr_@p#0d4pINZh2X)Ry$sEbmuSy~64X#=ec~ZfqETR^PyaG+ z&*}8t)LJapg!GJmORIF94Q=LVRnD5eM?@O>=+wzq(s`;(jZ3ynFNmNZ!4$Y?l|g|b zQ#)7d{MJi@CJBTDjBMHbv-x)_;zUq}W6{w`&%B}{$Ry}1z`R2LP988|@@OwqNxL)^ zD;#=aLCc|G8wdQjp5R_`1JWAgKohiWW)yEUD3{QF8>!9>Z?9Zy~RMnAWD;MW>eX zLlE@t!}ftC5;Bw_SshW#C%2au&f@Z%sz|yfifDw?!*9G&ym-VTpv{TeLY@_S%KNeY zA#Xe3y*OCD99&3g@f$$Vt7bBwxi1ckokj##R#iyJ(!=KsQnmojmoNY3YAI(Fs>SC_ zbG%=)O)mNtV5l6dL`hO$YMS&a<}~ zExm$WpTY!w=I1oLdjm;vas2OhSkx+ zo@lTY73foz)L1ptQDLV&DvHy&_V>zRW4qi$SN1 z90~9d3$Xi!D<+ZI9tNL#vIw?Ql{4WC#3O+TRa7pz3E%)hKV``>i!fj4e?VTG2*zR< z1rfs=yshiisy9(RxM*rcg;2U{qGa!turfEh8V#R0(> zoV$1AfrA2P7A*LAz3mH`7A96AFM&EQYwDaJfyq{gAZzI_0qPqt2T3u`fQZqX0K8r3 z=(`F$-FBG{;-B6L>fZn;{>|v0m!4R>Z-Ai`$V77lfT>F$PX;xG@fn0*7OKsa-{FxfF$TU)P5o{+=KGW%KfL(S8 zZtH$Urd4{=!gD+m|Eek}rJNO501|! zesKDw$J78EEVp>_CzRVL9{p@UFL-cyr=y!7Dd5$KDL2U0{Ze4Ohk0HEXCzvkUg?y4 zeZO)P!;=Xc0gosdrQrj{=i$EfyxG@!HeU-HL`vSKGx7G#nq?6`g%9;uiO;s8SZPCA z;B$XIF!#T%Iluqfii!C--hi$&UfkX*5a^}9R>wG11OHwRta4~=Uij)hsL;-h!3qqDnQgT>Mk1~n7;H;(K;@`*rVY> z9v{@wu${4Y?q2V@C7i4bJQ=N-i?cLH?q)3GhORUSokAZyi(vY-$@-o__E5M4be60m z20c<%fpBz4;e5M*2MMaG=^Y|1`3nWo*SF0y7ohh7U+J#Ec6%8rUS=Rk%ETp+hz{ZQ zs2-O47m6aIk+vU!ar4(rKy6D}*W%M;m-}i2fR#0Lfrk_vW$ZmM0{WqFI*I6)!%*iQ zT)c$Cam_`&mW+pd|y^Ta{Y zd@0!DJ-l`N#L9ce8{2O8 zt@M5z&8>7-tHI#Xc?B~Z;`A00w}J84AL3_Di_tWO$dOgNZM&Nv7rnRq?R;Sj*WwOr zWsUtLu^u;7SqGg^jKe(UAf!{l#H+PxzcDk!f4(pzUAz_n%7`e|+WoY1NmYAWig6U) zx5t2)H;TwpXi-hf#|9CiKBQ_;vw$ z)^6TzW>*(L&41e{Hat6|ANTEYwK|nhQ5zNLL>feDlD-(!X+nt!{*JqSGrc&i$=+F{@N(!ZnrfvQ%l7*m`b9H|w04uP##k>X3whWJKm2GeLeEc5v_ioYVc z(bf?8^w?!#!@fO9pF;Epvwc?yz#+{c~7=^k92uP#r6Rs?+Y={&XcAqzL_q zxK;IX<4`PM0m&st^S5Ib-DioPe1PmR79*$E6ocfJV*;XH7VX!qOn=g2><2**m?WwH za31&J^DuK8a7k<;qeg{s76jzGU>ZXi@kNK8_=BymbbdWaJ;iV!JV0n&o1cq$ic8}w zUhf@;u)NuKla+o$(gvzQR(~xXr#> zZFur7&C`cW;-wLVXsq?*`p9-H#cI;8MYT)~-Mgx9I8S)s{)R?3&rtKt456X+rbm(Y z=@RtEWAX`1svDEC(QSEqgk^0q%}vZiE-A0uefLh;3N?S`CdZ(3K)ar|TgaN%@Bv?F z3ofVe3;`y~cHb%7t!5G2vj;56GB*5uCn)!uHmO-kN4Mrk`}y2-xpjMd$t)@ZdNmo5V(Le`7M^>wvs-G zPJnVfR^^y+^iRE{9l@Qs2%)0?gZFFTp32rL|EN}Y^X}P}w%q zY#)r8_?J_kill+S}>LDEFT!`mK^ zge7EDCS_ls7_;u+^6;;z$DQZJaz6b@K4d8F^BGyL4a_%_gQ|><7g^5tJ9@e`JoDNR z2alU~_B5=U#zzzu=3+!rgz&e(0T`s7hDU(=+O{U{o-W2D^mtZ?MgR}oJ2uhnuEl0i@N0Pn zSbhf17_h*5ERXe>aPr%s?a5#d?k?LiazzD;lbs8^UEud0j%s|iTKtQa0|Mo-y|c25 zo}K)Rhj>7!LB6xouj9acR`idIkDBD`OzqbwCx6H!fohTeibWh3>8)s&t@YSWYVuu- zgs9%Dcy3RxL&K)n{xX19Zrc!lO_ul=)>a;5OUjMznp}hp2+%hKQZ^(3 zP*Q9=$Yl9cm(~@*q z)yvJQG{2Xhv|iL93~hdPs0hvM0dgC!TKfa4gHW6ka4Os zj;Qy*3r)w=XDe0E#^Oz1Cn=&N{fD+|f$K~~AjS4(FdM&J)7Bv>!aPG?Rq5oJk-LVA zWcDH)8#cqt<)E_>*DE9cKWf~@sv>uH-k9t^-Q44ysnhlF@wCga@vAc&O2(}M#Pd}x zO}p#2qWXoFbc{KC)6r>Hzu!|3LA+jAACIgKq8Ld(`DobjSD)d56s&$VcAmI;Qh)pT z&T`i1bzEcr=M(QG9BF;`;v){@jAI%L#ZpzpVe%gfydr&(I3L$xRjHy9Af$%!PiNV{ z{2HIWDDzY8AA|XIw~N5!-CC^0jSQs*8C@MfHjg<60kRs-$#>2eY`U_- zey!+|A3C}i&xZ~n&o6DB0FUbi6H?S%e&;L%)Pzm0a;WG^%tOomPUZj%cW}!Srf*;# z6l|>OibqrcSF-;OI&fXdU(L4E?qZZlL`)CC^LoN$=frg*c|UJ11ul30d#kH>UAVh( zbwk{4ep8O>9RF-W`1`5vh9q!r?xxm*zwfVb%XRTC3v6qpCb40UjR0j3^Av`wE`av+ zQ`4S?-Hd3PWMH&cti_$S8wM*pzv7K;(qX(DMeBu1W0 zvKngJO?w~PK!8io_iV0^yUAF}_lR#KnwA3e6u(Icoc{C5U}N6ZL=Ae`>G5c|h94VaH?w|dgT*rm zrJ7>O@QcK9Ri!emIkW{iOQ zDTZ4nDKc<zZRoX8|S;e6WiVU zg9J#w{O1}41F@G&I>fK?P|r6h_Kr0jX!WMDW|nfbYfV0En?=oi?G+ikY5&{eRURHN zM#Vlj(+6LjUPYfX23O1ElcX)6<@78|F}8vD&;*9~1+(8BeHK-{d&4D%zD^gO&oibl zt~)tP&NC>cTQ7=~`s(C^Ky-l8#G16=Pu`ixLuEbziRxiE4^%AxC2iIBs{tMJ0}^mH zV1WjlEM+7XZ^bqQqxp&^*v^;b?BdK4h+lh?R*A>MbE;8bjrUV?`v87{F@`l-z<}v$ zA@W#xA67D_szge*Z&RFC9`*-4MlIOr3y{%t&R-~h7ZY>od)=2TpX=1$54Wxmd%ZR& zOY}XKo`j2E$a=p}0F8_YK8G=Jl>#DK#pe@aBdMX_qSfhajY;((z!P!ca*p|#&^B(w z%{8!mP1kRvj#Y<%ott)CumxhJ$f@=Q1}7k0ll2_5*!V=Xy0y48U&7^Y?o96S(iDfK zb4E+XYohAES!P6N1-6d_XGQkS!lXi#R7r0qP7<$O5{A#{oPP$E9F&a~sfI)5}?!>OM1n6{XE^sn8K|lGMS`uzQl$qeEHNO$fSH z*;gY#aa@(@sn*Qw{QEqBqZ->!#FO+n10Yq69gQa8|LTK9Q9e?DVDD7R)ky#3q!tnI z(vn7BvO!fWru8~G!oh_&Wn?bVL)U&MFrweIM^R4(XcY@O^SA?jLeb z4^gUL+!=G0S5>8)j)2-Zby5sS+1de{#&D}iS?Y&jG(3MzrjxmqQ)a?)FiKLx(5ld- zR5_sN$Qy5~6?E<9y(EBa6yeZpudv@haoAG#(w^Jr{Ytz~ZpD29Fu$6l($G_YUI5Zp z!_+llaGubdR2sosQP2%)kgj zpWQUxr)O9Nq?Syk+Hd$TAV>EDd6#)hColxa``$zixZlNY|yj9D#Q|xjr&uKn4>-@^O72lL}icSA{ zIiR9cR>@bucb(Z{pq6@CzV*M`m`$D;Kya$5wfB4uDXL9rg5$t-I9VeR%)BtM9{C86 zPq{Z_BDTT2VyiRN?=}kJm6<5-BCHNTp__+m22^bf`P(dvgghUHUkz~H5jPV<)wHD- zCrU`)W&M>qfh7_Gt8<-Z%=;zMH^ImG_lM1!HW$h+c-2w`g;nzZ7}=hgzCsPq6Zmw* zk(#dLL7~6Ngz>?HxCxjcclp#+G5&5k`$j|G`p&Yxu4wc)VNz;cdmAn@8^49xSU{J^ z()a;5IIyKu9Tfk3GH8Yo0W3rP^sL3!r4z&;7oJ zalm`d->L=_GhhwP3tvNfFAV6HJk^%`eR@OQAbee$)I|oJC}9h>V=FIt8!-moXeToO z8*Qbm{(NSuUl4_k@KK*)jEtuXq%Ky8$RdA_5az>4%4*XS=1UJD-4l z4vF%?lZvea)-zkDXHWSh4-Zv2ytrAMFE!OKI-MQ@kVj_?R&4X`3lIRO;VUnh9&uXu z?o>iTT(o3q7uKKDOo-w!pW5CR8@kZWSv3cK?$!xxXAnnZ>~~hrpMOr|iPr$oxav#P zFwb4)@nDGFH>*2zjYS6Bw&GZaMl?!{KF0ynR29@j#vr2?lcdD_emDcVyNC^ykH6>a z;}}&RN{r~g&+SlS_&h--baCk`SjMgbVD<($CW!bxSfcG0l)R(l5KQYppLCjzZ}Fp%=gQk=;k#4s-R+WFks^;_-yGBg^rn;Hz z#5usEB&S9g^3akJ))m9fF*|td(nUKmn-&CRjI*NF({oi>kqG@S<1R2EBtoNAY>&3~ zC;VaG5M&N<+$KpN-MjGrQS#4{Z4X!o=n8q#{FEe}iqNBi71Bg7H|Ap{@w9R+4;dRS z)ZsJyvwrs>f_$R0KbBowwJdGq>LLtq+Z7>WYDArrf^Sl{eLqUWH>u-m8tCavUdO;f z$w!6bmR`b<7|i?I{H2qT%9F`84qd$EXP=31a;)iN~g5GrYvuxYc z?%TPdnWt%e5r2wz^kh*OKvZB=HKLTeW(e0U2aD^ejQA$rRkqmw)!tXO)s-yaBEj9= zAxLm{cY?dS6WlepYj6u2g1fsDG)QnK3GTsz-$iET%sF$;eV+RR?&cG$?%FL?Z@pFB ztg3CNtSi>lUeLC?BRybL2QCQ=Mb*EpS+Ra0!b4D@Cp)Ff_;(qQqbErbT~!5cFZmc6 z*XTx;EeXj$VurOn$S-x>L?O`^C1H#SdC{>18Cmm#59s% z``QvZL_Ic=W2cl`-bY&C7|rR|`0gw^^EUw{Tmr93-?^6yKM-r;ppj~Ya))yd&d~G~ z1LVe|%h&KV1Kvp zJYC;&7!&>|r+|RxmQPpAXqiz$KZ`#gsx+x;d*}2#cnvbNZ8rxnPqo!8^+A7jh&A## z;s8&7SRu8eg==6-Ikr9&`XH}t&Pf(?+73GqLjQRjz@^SL1-r)XR!2fC`Yf{rTX3hh zG7D<-%stvxyf9Nl03Vj0Lo!ze&g{0xDH4IZ5GqmMTCwn#uX|GuTq|29->9OR%JZrvakqI z1^MdJc|_^M-`sWb04Vp!F&6U85ND zxDGd`tbzL--WB*$w0K`{sPoqPJ?6CMDfBW)gR9VxcqPQ2L-0SYn-Fo`iu?Xb8(J;S}Q?pmt;S}O!U*)S{OuPJe8(?E05{LAIpRX#YdICV`eij z;f6K;y^8e+jj z3>c$(6r!j;gO!<#yfAVA$v z7~C6?U5bnDk4fN6Wyv`2u`4R?{bcXr=LO@X+6>x|cfq{HwTk;oO2m5911Qn(o|F5! zMyvM66-K)?Vj#5V<`3az(>$JbWjyz?b2|d}s9`~db6^Ad*YDrhNjya}-ZJ7vJw*E+ zw;-{bd(fGCppC%{#_Qtf)12EGfMFT;KOnYR>9%hbaTkr&GbESHJ>eU+I z<*rK++kias+YOk^0>e62#{7IsIggM0d3;ugfl(Z7nQ3?M%ykMQ=~t{G!+$Ko2R97m zue5DSTPXNqtKJLYT4(Ww)9=WqtDX)t49lVT)Gf1KHZii~2veW-d>pKGO~JGQ$IH*` ztB;_O%dve^Za3sLE=_rqvS%}0|3qzA#3m9JM=t*SFU7HA<7$)T-t5dz*6sx-=<%!XYq);1?Ws` zran&0Q;AikV9eAuEo=uPEH9LZ0E(rc9#=A1;@xv`-qrNZanHCae^@;&3`%h%A(;2C zh5u9gu6e6gEjl0ld_+U}bp2#t_ma&n3;jDF|DmF1PTIv}2O9QXty!H4aOCggyh=|q zzy+X})r)$7;Vnc!=j0>ojsN0y#m{%F^lrVcy7f*ITU0hrXSoiS1=BXyjJ|w2; z5^!-}Gi%bHDNbG~3DlI=>y%Bx_#m=da?$kzX3ZyI_Hp5tg+C#myz;CkfAoeWlMO#r z>kr1OSc)1zmU{u~5xz2s^3{7B8($Y8WPu0u#a3?`?&+!>o6>Q%_r#FnUt>q}Y{i2W zzV6#gDL3ss+$(L4nKmyZ#I$!-#5OB|?(DXe5OUPvyi1(LMNnSwD1iNtX8xCtXm@e- zNy|5}BqlSN?wq1XlsP=_5IGF9snXFGya7yA!g;SjL3#6xrfdF}`MWnPU6PH%rTZXW zv3N%p*D{4ETJpOug9S7sHR1gSoW$?AhbG~*&TOi&c{l{rERWFaC#ulomuboGD}Fa> z?k+ynH7t|=jYaQBm;fy-sX^vSSvdyK=u6T4$OEdk)ITd+m8(+layseombv)Ntt0~&H z_v=UTVkqHQ9@pMo_)~KR42oBLLrOX30)2&Wf9#Pfc&9dHxWZw>oM*PgYqz*0r{0BX zLglOb2^po=hmz_P{;{>r;=vQ32*K(zz*epuwK@j_5)FCtbF0;EWwCjy&b4sC+KgDw8ltrTpgZ@f&W zBNr0>1yHfRV(E7wqIa>mDi~$i?%@gqoMqP@0-7GMu4U(Q}j67tx>-ZQ|KAs%PP!e|6#f<+r&?F&Ia8IJ`x;;)RryC zJcX~-OgY_JrCNAeBe}5+={;;16E^!8yzcLFU9v|gp}LxFa7Ww97##)2HkuCr6{7b@a) zPaDLQ*UxDDNk9QM$9^O=_3k8Zav)NxM7NjJi#nuQDpXv{oCnl87RLI5ifQI<9>pw; z9oC0x!#jT%a23zyX;i*3l@`4-sShyWdL+|JiFR~xe{s5PHA`7HPJ71HoR>+jl6hpI zU0-Ho`9`pB{3}PkNbw$ocfBC8z^Z!Qg5f&ki*sz>1z-pS%(qRF9f0tH>SIhqZ-;tR z;`MBmdRG9QRnXT(-GaJ8v+}bdqShtEKjx^^SLEOk`m~hiUhf`E7~U$%#a25^1`9xs zsyX}Am(>k*4QhEcA^Etw%#a66k(unr66FsIb(+6C=h#IV)>|bmP|Trq2*{XPy*qN*iinZ za;*&WFGlgaIkg|%1XT^JCPDIucdOoSa4M!V1x;B4c%e*p4pW@~S{MQM(W1xp!fdOH zO?1D~qybC1#3n2dM}9h28K_T$tq_~g@d94OD()DyuLh9f@-L3NIMtZJ0J>a2CkObI`vEb!V)j6amYae~}-y5|ytCm}>@L zt``khUIK*{`|?C#2&Egd9ii}CIme89Qxtj{w7lwK;u6IXdo#rxFi7O7mDOUOI#V4! z=|5tfY}Nh9(R_paO<)k;QhJFaAG^(8+w3FuZDU~Y7~gB0E(@k}=bDpgA0ea6o0$29 z@q`<|)h4f%Tv~TTYT1{Npj9vYQdC4Kl^VC&T7X7I&Ka~aJipSEm*%7Dhe%en5#^w4 zAPxy^0Nkty^qM$f8s1dte%9kJDdxRC-SYF`7Z2{&uuOo}|S) z5MC}qjJw7)CgsJ=756hT3&f%drP^@wpNI35n1;Vcp7Ep`R##x&We zY*kjhq1}AZ3Ddj*GiQ6XKm5D2;JwqK^AurFfa1qBgRNJ`31+U=u~4q2Gl*@FVrulX;>a(VLEbXrd&s6ZG05)-T`&CNsg%zjZ zTtjj-H@fYqD=3y~>jl8Rm>%_&A3~bNa7}p@+fi^<7Ur+UfM7X30cAUP!a0>LHL+#d zkvGKD95HWxGN@VZq1ng%CbPS4_QzkoP4x%A(`K^8+Z)uGON$I7hNPldJ5n&O``rX* zDv@3Dhfh|hz~NPzov_2Rt1o%%2YkvywH$MRB>lGLV-7*>wYnEXuyzR8u;pKmNsG5H z5_u&!0uN}Y;%}}9*37f(txe+!&|-tFtb3;;R|(~LJFi=5r%co1w?lX5rPrGRR2h*^ zoyVlJ+;L0yalYUzm@OV%^*`#CC=AOJz+D8xE+m=gnE|F>eS-(s=j&bF?yy`Jfg)%r-ftgMVX&Rw z%9l(G^UUW>XSYX)P9!oWa0PD-TW4QG7z!nHF?J&Lr(c}oqVU8APV>&sov4Lnn<4?c z8b3)f;NEqL&}7M*SKM#mV^I1I>MuI;4$M4)EQ=|C(Gjq54fZ=v8l1S_KP2e5#cgZ&c7|z9$&+_ zR(7RTcl0X2Rau%2MM9b4_YgxK)A=%Sm-W18%pZZ>^^PB*_hNZV~X`>J(#7}yvk z;rPIvJxTMae|M^L8sFuL-dD}bPL{%9snk{?rCq_M{T=)L4q@{LvRrIZ*CWZ8JhQb( zwc`WPleK>Wa{eHdrGuw3Z$hiQNQQ_{qBx%RTXPlOH?x zaT6W!JrNEN@6t(;L`ZGj>wM$xgS~m=7ql*MxN*nTzEuiqP)*_@L8d5?TW^S9PMIiu zyZn2W9n(av5n4@y$ca~XUvc*is=tVEtO#2(*cQ6{rk&nRuJx1lFGjd-K^E1)S5hQ5 zSb=jIJRbMlE$GSivRZ%6a`+V5hyL6)4W{|Wel+KGnl~NPw1P|*dWSsO8$syI;+G)r zB~t$#W5&ssCwT%l~AuA<-1DIM@fpZ>*m@kqmo ziEZDUf35-3M@r=>9dwOwylMWO`~ZR)m&?YSAd%B|*w><(%`a>2b<1!yHUbbRGd~0_ z2`)6O7a;P}ahW1DS>olauYx^ND-k(dfHan7r zj23W5l6jbUpWQYjpo3jnQv;mNUu#=%i>$gF7CRnH5|7t*%3NMo}bQR&{gGdhsBaI zw$@;0I>4EvVhOeYiZlkI2g9h1dF5R>;dI74+zVro-vl%N`PSLbkd z#|iEX@RyXOOG)!#j(lL2vi?GQ=RMsH)jgo;1v?-mLRp~cM_iR}`*gxG}okQdb{_|99j)`QB8Hrs*to6f%lql4(AktO;_jb(`)(Z|b z9+TynL%&}X;zF9&r?x0CTqv-d>yJ@^pZS%Ns^L%hQqWP$>b)Wyy_#H!+4D1Cq7)9F z9`o)YpSzAgYtBuIUrK(BQ5Y=LE9*D^}P8mdY zUO;qVJO)6x{8u~=Hqp2&Xxc8-z~+r;s?Nu?E8m2EP0`TkjMO&RH1$z=^<3+IdF5R} z|0owjAWP!P`^n6vaa5I6quKeQ7yHF=_*T@GwGAgYzXbDlOLQB)iCHjrh3qJW{-*n? ztP^6&#>6IhxBR#%88ER{JAwHK>Rosg;l%T{E;ntjW<9>=@GM=iOcDOY7M-pXiMLi4 zP7t9xJ>D(K+dr25OaWNsF3D+;`sKSk+BQ{MZ_RNo|Cd;VcpNm-e!S=A9SGnyY6k-K z-d}<$(yq|b+`v0;fn2g-@~B@c2RM-X(MRk$e9q&TEd7I+x?PUcXWuU~_twtf`uz}F zA?QkBfP?apRuP?>^T0xH+BmrEk5$F{9n#*7cz1KUIbOV-*Rt*QNl>4JNcraFgmGZ4>PgL4~+ru%8hnF&AQST zq&GeCNxLBaSDx)2b0hp(DPMvkOD?7)c7Zli-=>@@TaJ&_Nd+kO8oO`Yhf{EwROcZU z)%!K3sChLC_negP%?MnhTCk?o<5Acab`azER@Hq6OS@0JI&Zp=0X-(8SD6T$XvvXn z-OMjq#msTya@lIJ&b;HldftBlRQSj9fp>ioCXip8}*`swaA4=FlF zov*Qn_t?hujsGR&I)if+)9qvgnDd)pv7yG-mWO4&4twuYILgoUIn=lwT{qRdo7sT; zS@nZuxvz_)J@H<8k-8wI7jeU=sv9SYr1_2rMW$EYo@k201Q735M%ic@a`jiC$cQQq znN{3CsPUDB%{ipL2coo>J^FF*QQ)g~J016Bje4L#z&`jT5Xm|H(sv7+sD=JJ6*1oyk!Z}3-o?qsR&X?lny`BFnGYAA2YQ1?5M0gsP8YgmshNoGS1vry;*ku@(g7bMQ zu0T?{y`*3=cdr5opO7zBxy)sIpK?(wX%SG?Ijvn;4&Qj-%ZwKy!gBIIR@~U`0-(b# zYfT&#*~=e7IVnaqfS+eWI;-fV@Yn1*)=4g7S{#tb?k2hq2@tXqJ^_}8fdhO^AFA`f)VCa`$ z-(>H2A>5A1fueXZ27~)WO!}NZc{IW+&!)ud&S|}D%QP;MMkpfsy^!vGmXz~_@M-dn z$inYdOMU!Gzy>N5UgV*T^DDW6uDRj?!eu0ZRnl!bfDS7onO1yT^)W;ng3xx6+2V~A zkYhn>?)wg?ics+P6F-8czGuBjdaq80q%Zn0-*rnQ^Gy&pI%QSt$>}_B{!mRIp+`;N zNiBy=-kBwd?pfLVG$EI^rL;l0W-^E`f83irq0>50BSUGI6nU-+%W*-(IEkK4xQAh985B6mM| zf)|_^i-O`+??0$E1uf(Kp@igBPfNf|AA`hDbg{TvycMut+HJe&YvzDlDn$MjN4OXw z=TzBs56x{Tg9}jN>33B+JyO1%=b6X*9nb^F`!oca!6|gE=3t`a<249Ob5@)KGY3K< zv)_3w-n*m7iRIH5TrK1+J|bIM+TJ3tb1xg@)x3t{d?dTqjdG3CSl$t%IT zTL#$WCGX!D!<{nmC&mDP+B)EONLVZI6|K2m#@+Sd9K`rsg`d_<4_?f=m)>*E-kYa7 zur1`1?=q$PW1T?iNTRw+*D7acuep$Oq4#W5A3TNA5>KFL5(HHAt`E4wYt0|R4`N!pV{~xwtSiC}Mp=yC zsur?lPiiZ)FCCF9<9w1Scq-K`K!e2Te)81D-Y6S)uQkwbiVNVi!J4z_^4F;lG;9)- z7wX_~z*^C7^`=WZRCimtt6y&N@4VX;Vr*K`2Q61MrB&{(om}nq_a8sBdeb%wRT`G3 z+>MbOj?1;GKCk);u6Eg%om=1Qskf(Xe;@g(y!*3IuR`au@1t8|yIoE;AxU#ob@}J# zE)Bnn?&Tq=%JS&r9|tBL9J&0MGre{?mqP1`(f1+&IEpTl!^#HP2l(eu2i2!Wt<>^P>Yzg#vLgfq)z!2MdseUs6$oVN zND;_*i#Q!9u^E?v9+8D{O!GELb9bTrP#4$k63#4E7O^rNpAQ>qI+-@LaDF6LYPJ%W zj=;-CcR;0LMGk4Md1?_6U$}==zFT?Yb7$tl#JLwhkFA+fp4QTNOwJW~%YF$t8Bqu} zZ1~X?^bqzrA=H?K@>>lqE<3Y%bRcM7+vr=Ktu7*BEH#LsW4B?`C(dPM&?DZ1$lZKy zfwLhC4((krIb=bp6@mlt@y<@7?ziJ{F+7Y7{^j~kdtwXLbgIdAmmBLs3IwsQ+PIzy zH6ROU3G03OV#x|#WcsnTCcMchwZY=l67G)|?6cX$fxDQ5Q9D}8z_Bqe#0(+PkDcoZ54;ycjHojKvL${T%1IB@;joTt!1Bzm|DQ{&-49kkG86m7no~zVB z0!^{belYIzQU5><%Id62xaMr>TDx2tuab>HB-k6C8kWl6`!O)w$IMb!qp3`}$jmZr zWkim|MSjvQalbJ%i~nAM{KOEayx3gbb@#%iF*>)%{qQzz&08W{W-+IrEy6qLARfvR z*_;2a)RwzxQn_^3Ne)H4LE*x_8@o`E=wPaV4VQ1Hjpn3%;citV(Pj7vwu-X_k{bk&Hdt|BxE^<(3BBng9j8G~Lw-BqJDV1+v z*lq6zH~38(83vm9hUUb4ID*JTEBqDd{@56pCHTvl^wW6)KTOGL5${$y!}4>v&y}JU zsyE*bm+TJP_U~YP^PdX3#=98TxUhRLRcGt*IK)=Q(TO=ArS!8z*c#e77N~j0E1YhL z-QG#&lv45AIBi%g?swJNzGlf#W@A6j3@oS`&%@L4sEi{CKk0|K^XzEWuI{GCDUW*k z^sUKP$L_Yht~HEL*M&>BjTrSfo;w3ks$uzXaYb;g8DZh%ZqMVQuoC=yi+Up26pCFpxtUIEW)Bh4lp%%i`^r^+qRpuun^Ba0M z(G_|(c@fJAJ^e{xybmWdgGG6_rfT9o6iHp3sA2BG(7d>_h^AH~+xP^CM|V)HEkTlJ zUIcG5$d^|Vrq-dw+La**{umikO)n-f{Nz}|ltEa?H7o8i68^A}k`6RvyT2{o!7u9W z2FK#CSb86F6()wrdV$}=m`nMlZ=|91V~?5nH8=024^%-6EkCB|2O*m;=*t9&Q^K&p zs)D%5^SwP)h6%zMjZ|Myixd+1tHneii4af1kfwu0tchO6#hX4Yc6Pf33@I!GniF?5 z7Jt!5X&D+R-hLwsC$p-(ALcPeC3|wBw7&Mx`BuJj@>8zJI_B<|aP)(|-Ct~xo6Qf0 z0&(uem9#oT4!q4(&aOm>jS}7Y=EP#~3?g5z75u7%QjL)5;0&**dEV}~inJ>RT$Q*m zqxbbR#J?guFq+af>*r7X%3T~xE1)A~!obQF=j+JMKq(O}$(^b!Iy8(28gq~(80nRU zg`5#YcPt4O!6RTNTHzjJVzPWVcWzoZH?g9OraipNQ3!sn+}@6Po?<(91ODuss%-#E z;aYm2MiIhXGm*O}1tGaq;L2=eXWG5}c`r|HQYu12x2fV?2#pALCU#Q37zN=N4ak%d zzDxnN?E#m92N%xRXjuvZ*^QaTl%nVqra3gOnhOunpQL3|{Z4XYMQzS-?&d1f3&Tgt zUa&e+kziS9S!i|y)HZw?Z&UDzQL}j7vvQp$ep1fVyF}6T^QF<%K(9!HyRMiJJbI1) z#$8@I))xdEk!WvAI|IA;L+-d~zQn2Z$PmWtDLOB z4XWt<9q1;ruMl&#birty0tc1v_<#3tS1?J3t-s9;iU^ghL$aYbC{YCdV`;ZrN87K8 zR{tI9QRr7WjG&zAbaUUYFx{^zLTKHq8wYWtqnXLX!FFy!zeG2pElg2(=Q>R;r z{%bhO_noNVM5r5{~>|y-Yull4IX}BUoLHqkfXW@Su?QsYfI$}cPdzv&!8 zF;#sJjw9X}&YqljO3*TViKI8Mc21W>ukbn_S>Dk;9~8-tB)?^C6;xP!rSu*?XiNW- zF+BxipJP4@V&r<}wJ2o>WC2wV3l=yU(VCK|^DuMmBt`oAncgHx73wehTRx5N<7@lEE#<_{H4BwH0@N97;8 z5Uyqf4##htZ$p0#!x{?5>k9a0z`*>lh~K{xNxol&Dk#|;7#EECFdQR3sf~}wLrs9f zBeg(O?=xV)#u15>AKB4bvSc>=x<`-QKvr7*=mctpG_yj5eTyE+dxBPi2x9}ABFxSn zFNBK^Jd*ECCRjZq8c{6{mI7G&c|DP33TN)yN$s{=uuU0m@bLr+o#&XP$(04?D*yGj zj|xjo%f970njf4w0vKO!n`nouoSbc)1bg`@R_;;PPkg%RO3z8GUd^E~nI^gtDtlf> z?2o&%ZJbU~oR#|aox|cvB2IDNkl>f*?fKo7 zoxS_AJPDSLsvD%cSFuf3oYn}j+91Z!3ssrqmQYIBRZ;XpWH50Vp`P5)0=1IpbA2gv zDtod>^yUQdQpjORyw^1hNuGXiG9M3KjqO%8)oVgBSXM(X%XfjR6-@KbfbFJ}Laz#= zLfVr?kSY9li^v`Pisc)05UwMn2%=LIIt%j{x6|Qw)#RWVo;E`S2Fq^j<+wbFgrZh# z?&wRx(*;p9g1!vONXX`dfk0j99}zPtQNbe%R$>MIOjr&|4^gr;`*v&P zfvLa%j$dz(O3%H8%$D#DyRjjS05=pt70WKlAp4GpKA^-^)86GlB!c=2{VnR+NCU24 z+c8r9hLxXC%c-LM;7nG#a!Yw9K^c_Q-N)~w5B*j@rJq3oTpiI>%(<(VA~@j(FyYlt zK(W97F52@1PA{GL3Jk0Uh-Z-g3~5}w?96}1GOJqefSPltPl86zfl6T@q8({xJ1%zy z%UTR@@V0zmRwEMlSIOc_12kU?N_tMFp4TZ#7kK?`r|9=^WPJGqC)dtS2F^ay8Se!~ z#GKF8uc{7-QX+YY&$L=Ty6t*QFeJ-lOQxSCd(LN?&41q7{WzGR$L8ElDo&1?Xp!5P z;LKBZOs|*l%Cgv3Mg=#rRk|jmD1Bu~1(nd;M!D~(Y7_D3)yym_x}=O}M8d1+fOB)| ztr2uNd?m?kov}J4^f>z+S{!a8Ft=^s_<3|b7U>KQ32M@lUQr}_d^0`F3}btWc$w6i zRpDYl(JV|fw|Kg~O&y1of(xz0ajHInOkfkOrzPO(u$w2%A%LZNV`}7-ntGyibG6&Q zo#pyWo#*Z>QJDf{YJh{I(?fDo&Cnh)-}lvF(+Wi6p)7YCG;c)dQo$MuR+7){4SRL^hN(}GNjUfGq5aq@nxMjWIyP1(Fk zw$3wU4Wj__mhrR7`*CmI`KteuqfUz6%9j;3AI6`{$JZ!^2~Ls}p(cVeCrUJ{9*osK z%gZ7x!ZQ&Su-ORQ*zgLFKSAG`j@*u~$%1G=Lq~;I;CF~E5u^txQmrU@Zx_tINYjgy zB&{n5QO-?uykm4S@eJ5^8E=#3)61Qio6?i; z+-213Di-Nyt~{T!KtVaTlbm~j7TgafYj-|9A(aFMS9YlILQvHxaHh?pLeFt;7Bsc( zu(()ZlELV%OU#M{$r>;}4vx!1mNZ~vSx?fdX6&As!!o7W9S3_dtTq_gtYsbqYd16D z#8fqOkn~l^p_3ImJFHES4B6P2)^+o(GKeTYz$cE;7_N+3@Ac z-5W1-)bEFxs!*%cHXHN~cPsAEB`r@a0;wt8`B1Us`S9;@5P@4D6-9{i<@&bqIk^iN zO@XgIpE?&=g0+tO>9noB_lmebdiA`D?1DOuly+-u)fCjr_4U&2oEGwPblp1&t8&9p za!_9)f@_r82poR<#1h(8({=`fGE!-q!M54OWX+p|cm2qZOc?EaQvnl2$=2d6sXK2j z3l9mMi{fgASOT|NbiRe>H?uV!)S<%nO0KPxd6$==l^%jmW^Rl2Y%k!eCl2U&CQG=m z9Cwy6YW4dBXS2%8l<8EADKGNs%oR26Vy65}z@BT)lI6EgRp*k9+SeiFtbT6;$=K2HB_{*akN*Fq zZ~<`7{s7bvWk&pb3VBV0xJJ+_!-5!Ck$*^XSz`j8)MTk%WD1Hhi-<|QoQZEr9JFp9 zv!~qX?^jIz#OOiru`yxlvr@!`3?nNnXDVX_!dXij-#slWC5G&#>3h*5@Xv)$Px1^Z zcBF}rU%1JQ$ZYa07^#-=IiacPVKmCpIm24yZSl%SwSm_!vI#jZEIf; z(}WFp$vqS3NUofHpRw6suF=qx-^}3{D4s=`D2k}fKXSM1eZzx|HN((r|Dm9BB89No z#yU3K7I{A93|5vH=79KZb3>>TT%(QkdQf3HtE)ptQ|Yh)qG-5k#5|=X1dE0xL1x!A zlFIZXOQ#8va0w+rn6Y78=jO8hp0>lcAG3>4h@|w{fD2;H*~rGl7`n;_bc?gYAdBEnD8bp}@9X zH|mX0y@l5mAbw9lgf#>&{H{R3?)0ttY^DHq)$?E9uKssrXK2GWSWig#>CP`VYpBXcB1L|39#3!r4d?vIBGDUy~RYTbqVPs9iE-6X8{n2N} zy`1QxcWBk+d^=mNZd+u&mkU?dI;DV{oCfT3W63O|RP{Dphg6{3TR06{C?4J*iLoEo zuQ!plmwTeWBH?NVBJs;;k7f}b=h)H=rk;wh5_pB5|Ii>9$rj2avd4Wk 0: + print(" First 3 rows:") + cursor.execute(f"SELECT * FROM {table[0]} LIMIT 3") + for row in cursor.fetchall(): + print(f" - {row}") + + conn.close() + except Exception as e: + print(f"Error accessing database: {e}") +else: + print("\nDatabase file not found. Please check the path.") + print("Current working directory:", os.getcwd()) diff --git a/my_project_data.db b/my_project_data.db new file mode 100644 index 0000000000000000000000000000000000000000..4bb877595f0c285f5e68e19f94da87e7d1cf7504 GIT binary patch literal 61440 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.8 +License-File: LICENSE +Requires-Dist: typing-extensions >=4 ; python_version < "3.11" +Provides-Extra: tests +Requires-Dist: pytest ; extra == 'tests' +Requires-Dist: pytest-asyncio ; extra == 'tests' +Requires-Dist: mypy >=0.800 ; extra == 'tests' + +asgiref +======= + +.. image:: https://github.com/django/asgiref/actions/workflows/tests.yml/badge.svg + :target: https://github.com/django/asgiref/actions/workflows/tests.yml + +.. image:: https://img.shields.io/pypi/v/asgiref.svg + :target: https://pypi.python.org/pypi/asgiref + +ASGI is a standard for Python asynchronous web apps and servers to communicate +with each other, and positioned as an asynchronous successor to WSGI. You can +read more at https://asgi.readthedocs.io/en/latest/ + +This package includes ASGI base libraries, such as: + +* Sync-to-async and async-to-sync function wrappers, ``asgiref.sync`` +* Server base classes, ``asgiref.server`` +* A WSGI-to-ASGI adapter, in ``asgiref.wsgi`` + + +Function wrappers +----------------- + +These allow you to wrap or decorate async or sync functions to call them from +the other style (so you can call async functions from a synchronous thread, +or vice-versa). + +In particular: + +* AsyncToSync lets a synchronous subthread stop and wait while the async + function is called on the main thread's event loop, and then control is + returned to the thread when the async function is finished. + +* SyncToAsync lets async code call a synchronous function, which is run in + a threadpool and control returned to the async coroutine when the synchronous + function completes. + +The idea is to make it easier to call synchronous APIs from async code and +asynchronous APIs from synchronous code so it's easier to transition code from +one style to the other. In the case of Channels, we wrap the (synchronous) +Django view system with SyncToAsync to allow it to run inside the (asynchronous) +ASGI server. + +Note that exactly what threads things run in is very specific, and aimed to +keep maximum compatibility with old synchronous code. See +"Synchronous code & Threads" below for a full explanation. By default, +``sync_to_async`` will run all synchronous code in the program in the same +thread for safety reasons; you can disable this for more performance with +``@sync_to_async(thread_sensitive=False)``, but make sure that your code does +not rely on anything bound to threads (like database connections) when you do. + + +Threadlocal replacement +----------------------- + +This is a drop-in replacement for ``threading.local`` that works with both +threads and asyncio Tasks. Even better, it will proxy values through from a +task-local context to a thread-local context when you use ``sync_to_async`` +to run things in a threadpool, and vice-versa for ``async_to_sync``. + +If you instead want true thread- and task-safety, you can set +``thread_critical`` on the Local object to ensure this instead. + + +Server base classes +------------------- + +Includes a ``StatelessServer`` class which provides all the hard work of +writing a stateless server (as in, does not handle direct incoming sockets +but instead consumes external streams or sockets to work out what is happening). + +An example of such a server would be a chatbot server that connects out to +a central chat server and provides a "connection scope" per user chatting to +it. There's only one actual connection, but the server has to separate things +into several scopes for easier writing of the code. + +You can see an example of this being used in `frequensgi `_. + + +WSGI-to-ASGI adapter +-------------------- + +Allows you to wrap a WSGI application so it appears as a valid ASGI application. + +Simply wrap it around your WSGI application like so:: + + asgi_application = WsgiToAsgi(wsgi_application) + +The WSGI application will be run in a synchronous threadpool, and the wrapped +ASGI application will be one that accepts ``http`` class messages. + +Please note that not all extended features of WSGI may be supported (such as +file handles for incoming POST bodies). + + +Dependencies +------------ + +``asgiref`` requires Python 3.8 or higher. + + +Contributing +------------ + +Please refer to the +`main Channels contributing docs `_. + + +Testing +''''''' + +To run tests, make sure you have installed the ``tests`` extra with the package:: + + cd asgiref/ + pip install -e .[tests] + pytest + + +Building the documentation +'''''''''''''''''''''''''' + +The documentation uses `Sphinx `_:: + + cd asgiref/docs/ + pip install sphinx + +To build the docs, you can use the default tools:: + + sphinx-build -b html . _build/html # or `make html`, if you've got make set up + cd _build/html + python -m http.server + +...or you can use ``sphinx-autobuild`` to run a server and rebuild/reload +your documentation changes automatically:: + + pip install sphinx-autobuild + sphinx-autobuild . _build/html + + +Releasing +''''''''' + +To release, first add details to CHANGELOG.txt and update the version number in ``asgiref/__init__.py``. + +Then, build and push the packages:: + + python -m build + twine upload dist/* + rm -r build/ dist/ + + +Implementation Details +---------------------- + +Synchronous code & threads +'''''''''''''''''''''''''' + +The ``asgiref.sync`` module provides two wrappers that let you go between +asynchronous and synchronous code at will, while taking care of the rough edges +for you. + +Unfortunately, the rough edges are numerous, and the code has to work especially +hard to keep things in the same thread as much as possible. Notably, the +restrictions we are working with are: + +* All synchronous code called through ``SyncToAsync`` and marked with + ``thread_sensitive`` should run in the same thread as each other (and if the + outer layer of the program is synchronous, the main thread) + +* If a thread already has a running async loop, ``AsyncToSync`` can't run things + on that loop if it's blocked on synchronous code that is above you in the + call stack. + +The first compromise you get to might be that ``thread_sensitive`` code should +just run in the same thread and not spawn in a sub-thread, fulfilling the first +restriction, but that immediately runs you into the second restriction. + +The only real solution is to essentially have a variant of ThreadPoolExecutor +that executes any ``thread_sensitive`` code on the outermost synchronous +thread - either the main thread, or a single spawned subthread. + +This means you now have two basic states: + +* If the outermost layer of your program is synchronous, then all async code + run through ``AsyncToSync`` will run in a per-call event loop in arbitrary + sub-threads, while all ``thread_sensitive`` code will run in the main thread. + +* If the outermost layer of your program is asynchronous, then all async code + runs on the main thread's event loop, and all ``thread_sensitive`` synchronous + code will run in a single shared sub-thread. + +Crucially, this means that in both cases there is a thread which is a shared +resource that all ``thread_sensitive`` code must run on, and there is a chance +that this thread is currently blocked on its own ``AsyncToSync`` call. Thus, +``AsyncToSync`` needs to act as an executor for thread code while it's blocking. + +The ``CurrentThreadExecutor`` class provides this functionality; rather than +simply waiting on a Future, you can call its ``run_until_future`` method and +it will run submitted code until that Future is done. This means that code +inside the call can then run code on your thread. + + +Maintenance and Security +------------------------ + +To report security issues, please contact security@djangoproject.com. For GPG +signatures and more security process information, see +https://docs.djangoproject.com/en/dev/internals/security/. + +To report bugs or request new features, please open a new GitHub issue. + +This repository is part of the Channels project. For the shepherd and maintenance team, please see the +`main Channels readme `_. diff --git a/venv/Lib/site-packages/asgiref-3.8.1.dist-info/RECORD b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/RECORD new file mode 100644 index 0000000..1770b42 --- /dev/null +++ b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/RECORD @@ -0,0 +1,27 @@ +asgiref-3.8.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +asgiref-3.8.1.dist-info/LICENSE,sha256=uEZBXRtRTpwd_xSiLeuQbXlLxUbKYSn5UKGM0JHipmk,1552 +asgiref-3.8.1.dist-info/METADATA,sha256=Cbu67XPstSkMxAdA4puvY-FAzN9OrT_AasH7IuK6DaM,9259 +asgiref-3.8.1.dist-info/RECORD,, +asgiref-3.8.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92 +asgiref-3.8.1.dist-info/top_level.txt,sha256=bokQjCzwwERhdBiPdvYEZa4cHxT4NCeAffQNUqJ8ssg,8 +asgiref/__init__.py,sha256=kZzGpxWKY4rWDQrrrlM7bN7YKRAjy17Wv4w__djvVYU,22 +asgiref/__pycache__/__init__.cpython-312.pyc,, +asgiref/__pycache__/compatibility.cpython-312.pyc,, +asgiref/__pycache__/current_thread_executor.cpython-312.pyc,, +asgiref/__pycache__/local.cpython-312.pyc,, +asgiref/__pycache__/server.cpython-312.pyc,, +asgiref/__pycache__/sync.cpython-312.pyc,, +asgiref/__pycache__/testing.cpython-312.pyc,, +asgiref/__pycache__/timeout.cpython-312.pyc,, +asgiref/__pycache__/typing.cpython-312.pyc,, +asgiref/__pycache__/wsgi.cpython-312.pyc,, +asgiref/compatibility.py,sha256=DhY1SOpOvOw0Y1lSEjCqg-znRUQKecG3LTaV48MZi68,1606 +asgiref/current_thread_executor.py,sha256=EuowbT0oL_P4Fq8KTXNUyEgk3-k4Yh4E8F_anEVdeBI,3977 +asgiref/local.py,sha256=bNeER_QIfw2-PAPYanqAZq6yAAEJ-aio7e9o8Up-mgI,4808 +asgiref/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +asgiref/server.py,sha256=egTQhZo1k4G0F7SSBQNp_VOekpGcjBJZU2kkCoiGC_M,6005 +asgiref/sync.py,sha256=Why0YQV84vSp7IBBr-JDbxYCua-InLgBjuiCMlj9WgI,21444 +asgiref/testing.py,sha256=QgZgXKrwdq5xzhZqynr1msWOiTS3Kpastj7wHU2ePRY,3481 +asgiref/timeout.py,sha256=LtGL-xQpG8JHprdsEUCMErJ0kNWj4qwWZhEHJ3iKu4s,3627 +asgiref/typing.py,sha256=rLF3y_9OgvlQMaDm8yMw8QTgsO9Mv9YAc6Cj8xjvWo0,6264 +asgiref/wsgi.py,sha256=fxBLgUE_0PEVgcp13ticz6GHf3q-aKWcB5eFPhd6yxo,6753 diff --git a/venv/Lib/site-packages/asgiref-3.8.1.dist-info/WHEEL b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/WHEEL new file mode 100644 index 0000000..bab98d6 --- /dev/null +++ b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.43.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/asgiref-3.8.1.dist-info/top_level.txt b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/top_level.txt new file mode 100644 index 0000000..ddf99d3 --- /dev/null +++ b/venv/Lib/site-packages/asgiref-3.8.1.dist-info/top_level.txt @@ -0,0 +1 @@ +asgiref diff --git a/venv/Lib/site-packages/asgiref/__init__.py b/venv/Lib/site-packages/asgiref/__init__.py new file mode 100644 index 0000000..e4e78c0 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/__init__.py @@ -0,0 +1 @@ +__version__ = "3.8.1" diff --git a/venv/Lib/site-packages/asgiref/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2337617f83ba346b15d31afa8c4746ef6ae8a351 GIT binary patch literal 213 zcmX@j%ge<81d9wKGQ@!NV-N=h7@>^M96-i&h7^VBq-s=4F<|$LkeT m-r}&y%}*)KNwq6t16l=gUopt}AD9^#8E^23HgXrS0J#96T{|uS literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/compatibility.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/compatibility.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82c4c191e2fb8541e3c7da07e4fe54594fd7f995 GIT binary patch literal 1797 zcmZ`(-D?|15Z^tWbQjCE+9-At=R@0%v{7qIsa+^ECeRvO`avkzf!2ts>$|ml&iPL4 zu54s0#3i9|p$~=9T73(B3#O32p|5>Wu_4YiZ%v_j3y~i}o;rJ{vn7`<+-P=Zc4jrd z-^}j=1APeAFK>UoIGsZ1FSUu6)=}DTg0h8dWMdc2AzQN(E?(B=G>mNh7Me@gNszjo z0-3Diyzy9Fyz&@>%;O;I2+QYwO*$T1sCkxje9uz0cqKtez}Nl_#1@hVwgzOhwQXgC z#c^Hhu_bzJy6pHNw4_Hjx@7}xcj7`ET^g|sawNAq|CA5QV~6KUVP)cd^xG9f>-LS$ z`_T-_r`EpcBd}(fkb+2`2*!xBK&VG(wdy(+RV5&fAe6YQLaq9kkad@l3$|aIciEUl zU6+EA@AfZ*F@vEp6&0r}9IxWCa_l)BpGOf6&SwL&9B#_xd@3+1Oj0R%U^t$rGE0IY zESCxq7>iUW6IZ3Gn?zJGZXi&?i!c&GAAAygWdb=BV+LPjjwNfzrJg{x|dPg z&GqKTyT%*)Db$~9uHVm1{E?g3O~133J^3i}%AHF)nPMwlZ0W@|WI#RaRNM&Jc^s76 zz|T#zfNgxsyp9_f(AL&wBD6X6#DdS46|6^qB=66B_)#~Q#PNU^lteHd08V_5ML1h3 zWxNz7Kfu@i0K|{@6NKRz8v0g0B=z-#h8l?mZfG%?Z$iVaLzJJit;9FUBoOmm^qu}| zVio7{mAfdP43f~7RTdbWSjeCMPGK}YVag4b6NjNo*EkF!Vn{ilzU8wB9m4`PpH4DVpvl?09rI2Iv7-H z6q-RYc9ara)&GKWR|-JTkIa$gTf4^V4~L8Q(mTVGo9Vsua7!N!@yMsRn!!NKx@Sd` z=`gE`5ON`OjWU~)%f4N6*=2qXtZHHjh5C~O#`sS(_%}NLG?m2{pN<~Gr`sn@{8D)L EUkHiNfdBvi literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/current_thread_executor.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/current_thread_executor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f04d8200b31d0f8c83f45d575579651b4ec5d5a6 GIT binary patch literal 4986 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/server.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/server.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72a254b277378e4ed3e754318e0ae7a890565528 GIT binary patch literal 7956 zcmbtZU2xl0cD?|AL{iX?CE5CyVOp|8Tasxzab($!tv@^diQ2^5*7kTyLj)v21_>4b zEs>#TT*uRuJD!Plx?Lx`ZP(N3w9dGl<}rEOqz`@Qi?Fgo2CIj3x}Dj5lcnr5&h(+@ zTo53|F!t^gBV7RZUYvXGx!?KjxrhHzR~I61{r#cK^XXPX{tI86%UgWdnumu6L?j}k zkgN8cxysOY_9{#7o~s^_6+MbK;k)W%2umbpfpY|v?o!QT#(ujRV98k`dhZg^_n0l# z1v5;<{~LUn{tfnvFjo6qTF``~AxSY^PR=P(EG{UDFr!Fu`y;z7N+4So;r#)T2INnvi=!3FG^g|gCYoH8@0VqRa5XxFH1SKcdLRpvLBK20oB||VI zMbh<4l6F(lge4y#As()AL6>-)R`PL0&~@IJ7Yu%0NQ%&%pAmF9&d1ecTuK=_ugEtf zUPz@BIW8Eon&joAZV1pwWyLj#)*ei$ssb||}RgDJ; zwr+e%Qw=q)DmoQ6AP-B!yqW|x7G+~zO&h!rH`0OvqsG+)2t&n^QXB^Wy;V?MLK$(G zXCy>rTv5{+^b%o?AV3j$6=tu=@Q!`$Sq?<_gaq=%L0(i*>LOS`f_}Vg@JUG$QT8Ae zhq~k9VXryKh^bnPPFjkU871Zzg{sX9d^#!rSz6++>v1(D#boiiE6c9BPR)P{(H=PL zBH)Ei2}T*Vr*dwV7m`(t&&xVUNP})@Cpt4-NR$sa$Y<0vFKG5U&B-?Ta*D0U~`n25Wr5jLilk>G|mFed=tzlx>G3*z}vzph-NiOp9c#rmX9;c zPl1wP+(jW{t5sYXQKhnU6&C{yj9?qJ=T7yEQ9b#S09R#p_~qswpz;vp;WQw8=+NOK zue^FRY_B9%zY{hxDJeY4hYd+L9Pot)?f$S(*yMa=S0=%(SPMYVq{Z+pTUdmSRHo!G zm^GGE7X{fENB|mzIjIOpSVgpyp=Dq-0ZiyJ;8NeQu-FBS1wHUzf!<<<4t6~uER}=q zy6cMiAVq+xh%l*xiX`X;uSsz!X($;U3;{j>%eyEm3O{4x0a_J7PCyHer_TcPMW71>Mjt@0%J7Gx(S+^d zGZ|i#W`(q3MCjP_!cFR#vR0xF9k3EeWkVVQ%-jIj>(>N* zPS&K^gZ3sfoXS{%7$_hcu~@dPVqY3|TF?l32Nbu-m!12Ty-xyd1wM-R?l1fLm%UE| z;Voz-an~sDg1bF6;WzN`fEaGuf@>^jC|-|?_ghR^KPO&rI>9|h7HY~~i;vFNkBeh4 zBuH}10$Q=+g70f9s^In8-)Gpp#Bk${UZS-z#He?^T-f0}mF^-_8vP2%u#05LbA>E2 z5l?oK0u4Ft?KEzUu(b$!CK;Di9$XMSK~dF|P3gEn+IZGzt&LIqG`o9hNe1_x<3-rL zz;`ALO&OXvh|Z{K>69@Y30gHpxmGpo!<4;Vi$R&do`h<&~4OYJ}C$T2`nurjEPKB>dx;xVD3DywsUAXv>s^42fEEb_xobL=cw6pbggIP zN#NK9>j@q&aJ%wc#N;B6djIvnhX)=HJ>^EeUT@$x2@^cN&NaPv;ogPSwqu`jqZ=Nm z`9{YT`(*c6JNdM|XKd8-=`jY%ZFohjz6<|bJQNoQvkkMQ)xE>~iw9Pfoz8Y%0rE+t zfzZL}6e)o#>BKM}GFJ1nYMgT#BykGqIKogf>4;O?GTJV9%UF;nYP)?LVw6BUq%8`a52O?TGs2=gyfbr2F%c?2v%MRb!sA;VHILlWWsptS%0 z7|i`6hD)i{j%dzkw>(CJqaWzi=scJ1&Wvt(%OoQFD=wDgy!Y6gX93r_;#y{x$t)Zk z?*{(a`?$DTu3TTvlk?qUf45Z>eShPvZuuNt!<^?5iTJZ`xGpq7qepa*a))svLFzb~ z1pEto0EYWCfG&BD6@&wy5yP0!sx6CNw~-WjeKY)T4M6eNfYy8Lg1fPnOmPq573UCq ziD-y&pq{;W^JrnXX?w6h%C=bh zhETJ-2E@mfN0E{=NV38roTd#aW=GlOfw&u6X}AGczPIpjrJ)t=7z=G_d0=W0zs*Mh z=U8ZuO7&~{~r7__;0n#lX-5R$?bc%WOC7uI!*3mp}95RJY+TxJ(@S0U;DVuY(BHf zo%vP$j+Neg)1cWjxK=;(kvAWmGNV(!sGllujd|{f$sKvZz511hG&EJ|wpKs&m7lcs zJV^X7@mK0{?fUMKk6ZG`&Y8!~t?dSq?fTV@w)~EL=8k<|aC~7`XQ6HH&l)~xSl@a6 zs~T@z{g%hy6k7IgG?K3V!mh5u&W`o=?w_@P(EiiTXF*>ywCv3X!e$`+aKsD@Zg8Zr zb2ZRGp|Z^lkhUmo{{kM$V@r{_i!maG9u?PuOLe6Nhngn86#?D?2dXON1<~gu`94p` zH5mIAd&`r9JP{Ikj=2H8sx$W+Kw=d#&an0Bi{#wV5*SXLREjvJYX1dzZO&|200pf-Smef!dmQb z)T$9BLy#4HTWA+NF()OZrIhx1cB&HDFZatb&TzyeVN813pi$2TVLL)!L@z!3ljXB3 z7oKvw8NKver_oQt4#rk6;l5Y9n+>_9)&Y}+0d>Dv^My<6);y_x_ z4#Du+2)x3%LLPN)!lB_BO+M$hM?Z<*1zoSAVW7$L(p$vW=uC! zNE(QxR1$=xNyxI;(jb3FgIGLv#nYOGVY&{4?+#0u9M0^;y+wqCjOCAG9#ttusb!eJ zdApD}2`||L-vRn+fLnqO^m9-EjfV)ZGiBjNm(8Z5%QcjKZ318AqPWmYW&@vZ=rbGo zo;36qxaO5N00nuj*W`Mia{D$sq;a4+H@*u)Y-J%ZupK@4lG8V=H)6fwdRz=F-i4s` z9hmoz*$1A#@cDqH43`DrOAIb5uHWU14Q%jUzc#P3bLtzEo1mE_wR;fAw*#rChYZGqCpR_X|p@L{Js?YAN^r|X)-NA1^fx_M> zLZqR2y{Y}d&<}?mdh`64$&alyjpw=XRc?H}4>AS${gdYY$^8EF=Kk|*`!9ap_omsn zXC?4{f1$bK{SmXdH{TpFn!rOj_jLeHhiE^fgArCT)q8G<~hVo zUA>!x-P!%0ZCx8axc{$y5wyS4JARz`M`nD$`%hy89zPw}59Mb~%=mu)XU$%GZmSy~ zWIyYp&-)py84Qk(_&$4;#pl-;d>-+@^R~k+MjMm~egY4b8I5YujfkNDTP;#5d3-g0 zhg@3-hN!q4{&4Q1C&&Dh{4M*q$ThG7c&VrOvKL)gPe5uKlFOJ7#`JXMVaiQ%L#Bmp z6fVe0xX$)Xxj%G4w2nV7m4RoJ@6$tldY^8QEX(uL5x-S~nJmbxSw89`mUjVuc(Q_q z28s3=NSs_3xd%clJl;@-6*lOaG%_e&CcjaB8jP^cpu-sBc_pU#VT? zx_%q<1w+s28RgDcaI6**(~SIU&CSp;#=TifQ;EG-h!z_*q9#iY+y< zn5f2MF>Mm`&@lU{bz*@jD|(pJFrd^hFw$@<)X;M^oTPRX3*=~eEYk3pM2lK@&`&{e zmpo&8e1VPA4C(D(_3~R@pKoBZDd;=Cxr_0QF`Is`?*g;g*y-!s9OZnin_U54|7J_0 zuY0RE=nL7hQEZXFvj5sJ@k literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/sync.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/sync.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9929c3653013cf0317df84e2f81d37874922113f GIT binary patch literal 22926 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 NEBCe&klAtbzX9Xu2etqJ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/testing.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57581bf6f32afb989752a47ce0480231492eb1b9 GIT binary patch literal 6070 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 LG`L1E*ERePGD*@6 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/timeout.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/timeout.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd74fa99050f5e7a1da55dbc80fc141721559a6e GIT binary patch literal 4896 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 Wus?8ifA-4$z?E|M^FQcdqx$c|OKn8} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/asgiref/__pycache__/wsgi.cpython-312.pyc b/venv/Lib/site-packages/asgiref/__pycache__/wsgi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d40571bba7a13927f42452ed894c5ac9364dcd9 GIT binary patch literal 7300 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 (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +_T = TypeVar("_T") +_P = ParamSpec("_P") +_R = TypeVar("_R") + + +class _WorkItem: + """ + Represents an item needing to be run in the executor. + Copied from ThreadPoolExecutor (but it's private, so we're not going to rely on importing it) + """ + + def __init__( + self, + future: "Future[_R]", + fn: Callable[_P, _R], + *args: _P.args, + **kwargs: _P.kwargs, + ): + self.future = future + self.fn = fn + self.args = args + self.kwargs = kwargs + + def run(self) -> None: + __traceback_hide__ = True # noqa: F841 + if not self.future.set_running_or_notify_cancel(): + return + try: + result = self.fn(*self.args, **self.kwargs) + except BaseException as exc: + self.future.set_exception(exc) + # Break a reference cycle with the exception 'exc' + self = None # type: ignore[assignment] + else: + self.future.set_result(result) + + +class CurrentThreadExecutor(Executor): + """ + An Executor that actually runs code in the thread it is instantiated in. + Passed to other threads running async code, so they can run sync code in + the thread they came from. + """ + + def __init__(self) -> None: + self._work_thread = threading.current_thread() + self._work_queue: queue.Queue[Union[_WorkItem, "Future[Any]"]] = queue.Queue() + self._broken = False + + def run_until_future(self, future: "Future[Any]") -> None: + """ + Runs the code in the work queue until a result is available from the future. + Should be run from the thread the executor is initialised in. + """ + # Check we're in the right thread + if threading.current_thread() != self._work_thread: + raise RuntimeError( + "You cannot run CurrentThreadExecutor from a different thread" + ) + future.add_done_callback(self._work_queue.put) + # Keep getting and running work items until we get the future we're waiting for + # back via the future's done callback. + try: + while True: + # Get a work item and run it + work_item = self._work_queue.get() + if work_item is future: + return + assert isinstance(work_item, _WorkItem) + work_item.run() + del work_item + finally: + self._broken = True + + def _submit( + self, + fn: Callable[_P, _R], + *args: _P.args, + **kwargs: _P.kwargs, + ) -> "Future[_R]": + # Check they're not submitting from the same thread + if threading.current_thread() == self._work_thread: + raise RuntimeError( + "You cannot submit onto CurrentThreadExecutor from its own thread" + ) + # Check they're not too late or the executor errored + if self._broken: + raise RuntimeError("CurrentThreadExecutor already quit or is broken") + # Add to work queue + f: "Future[_R]" = Future() + work_item = _WorkItem(f, fn, *args, **kwargs) + self._work_queue.put(work_item) + # Return the future + return f + + # Python 3.9+ has a new signature for submit with a "/" after `fn`, to enforce + # it to be a positional argument. If we ignore[override] mypy on 3.9+ will be + # happy but 3.8 will say that the ignore comment is unused, even when + # defining them differently based on sys.version_info. + # We should be able to remove this when we drop support for 3.8. + if not TYPE_CHECKING: + + def submit(self, fn, *args, **kwargs): + return self._submit(fn, *args, **kwargs) diff --git a/venv/Lib/site-packages/asgiref/local.py b/venv/Lib/site-packages/asgiref/local.py new file mode 100644 index 0000000..a8b9459 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/local.py @@ -0,0 +1,128 @@ +import asyncio +import contextlib +import contextvars +import threading +from typing import Any, Dict, Union + + +class _CVar: + """Storage utility for Local.""" + + def __init__(self) -> None: + self._data: "contextvars.ContextVar[Dict[str, Any]]" = contextvars.ContextVar( + "asgiref.local" + ) + + def __getattr__(self, key): + storage_object = self._data.get({}) + try: + return storage_object[key] + except KeyError: + raise AttributeError(f"{self!r} object has no attribute {key!r}") + + def __setattr__(self, key: str, value: Any) -> None: + if key == "_data": + return super().__setattr__(key, value) + + storage_object = self._data.get({}) + storage_object[key] = value + self._data.set(storage_object) + + def __delattr__(self, key: str) -> None: + storage_object = self._data.get({}) + if key in storage_object: + del storage_object[key] + self._data.set(storage_object) + else: + raise AttributeError(f"{self!r} object has no attribute {key!r}") + + +class Local: + """Local storage for async tasks. + + This is a namespace object (similar to `threading.local`) where data is + also local to the current async task (if there is one). + + In async threads, local means in the same sense as the `contextvars` + module - i.e. a value set in an async frame will be visible: + + - to other async code `await`-ed from this frame. + - to tasks spawned using `asyncio` utilities (`create_task`, `wait_for`, + `gather` and probably others). + - to code scheduled in a sync thread using `sync_to_async` + + In "sync" threads (a thread with no async event loop running), the + data is thread-local, but additionally shared with async code executed + via the `async_to_sync` utility, which schedules async code in a new thread + and copies context across to that thread. + + If `thread_critical` is True, then the local will only be visible per-thread, + behaving exactly like `threading.local` if the thread is sync, and as + `contextvars` if the thread is async. This allows genuinely thread-sensitive + code (such as DB handles) to be kept stricly to their initial thread and + disable the sharing across `sync_to_async` and `async_to_sync` wrapped calls. + + Unlike plain `contextvars` objects, this utility is threadsafe. + """ + + def __init__(self, thread_critical: bool = False) -> None: + self._thread_critical = thread_critical + self._thread_lock = threading.RLock() + + self._storage: "Union[threading.local, _CVar]" + + if thread_critical: + # Thread-local storage + self._storage = threading.local() + else: + # Contextvar storage + self._storage = _CVar() + + @contextlib.contextmanager + def _lock_storage(self): + # Thread safe access to storage + if self._thread_critical: + try: + # this is a test for are we in a async or sync + # thread - will raise RuntimeError if there is + # no current loop + asyncio.get_running_loop() + except RuntimeError: + # We are in a sync thread, the storage is + # just the plain thread local (i.e, "global within + # this thread" - it doesn't matter where you are + # in a call stack you see the same storage) + yield self._storage + else: + # We are in an async thread - storage is still + # local to this thread, but additionally should + # behave like a context var (is only visible with + # the same async call stack) + + # Ensure context exists in the current thread + if not hasattr(self._storage, "cvar"): + self._storage.cvar = _CVar() + + # self._storage is a thread local, so the members + # can't be accessed in another thread (we don't + # need any locks) + yield self._storage.cvar + else: + # Lock for thread_critical=False as other threads + # can access the exact same storage object + with self._thread_lock: + yield self._storage + + def __getattr__(self, key): + with self._lock_storage() as storage: + return getattr(storage, key) + + def __setattr__(self, key, value): + if key in ("_local", "_storage", "_thread_critical", "_thread_lock"): + return super().__setattr__(key, value) + with self._lock_storage() as storage: + setattr(storage, key, value) + + def __delattr__(self, key): + with self._lock_storage() as storage: + delattr(storage, key) diff --git a/venv/Lib/site-packages/asgiref/py.typed b/venv/Lib/site-packages/asgiref/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/asgiref/server.py b/venv/Lib/site-packages/asgiref/server.py new file mode 100644 index 0000000..43c28c6 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/server.py @@ -0,0 +1,157 @@ +import asyncio +import logging +import time +import traceback + +from .compatibility import guarantee_single_callable + +logger = logging.getLogger(__name__) + + +class StatelessServer: + """ + Base server class that handles basic concepts like application instance + creation/pooling, exception handling, and similar, for stateless protocols + (i.e. ones without actual incoming connections to the process) + + Your code should override the handle() method, doing whatever it needs to, + and calling get_or_create_application_instance with a unique `scope_id` + and `scope` for the scope it wants to get. + + If an application instance is found with the same `scope_id`, you are + given its input queue, otherwise one is made for you with the scope provided + and you are given that fresh new input queue. Either way, you should do + something like: + + input_queue = self.get_or_create_application_instance( + "user-123456", + {"type": "testprotocol", "user_id": "123456", "username": "andrew"}, + ) + input_queue.put_nowait(message) + + If you try and create an application instance and there are already + `max_application` instances, the oldest/least recently used one will be + reclaimed and shut down to make space. + + Application coroutines that error will be found periodically (every 100ms + by default) and have their exceptions printed to the console. Override + application_exception() if you want to do more when this happens. + + If you override run(), make sure you handle things like launching the + application checker. + """ + + application_checker_interval = 0.1 + + def __init__(self, application, max_applications=1000): + # Parameters + self.application = application + self.max_applications = max_applications + # Initialisation + self.application_instances = {} + + ### Mainloop and handling + + def run(self): + """ + Runs the asyncio event loop with our handler loop. + """ + event_loop = asyncio.get_event_loop() + asyncio.ensure_future(self.application_checker()) + try: + event_loop.run_until_complete(self.handle()) + except KeyboardInterrupt: + logger.info("Exiting due to Ctrl-C/interrupt") + + async def handle(self): + raise NotImplementedError("You must implement handle()") + + async def application_send(self, scope, message): + """ + Receives outbound sends from applications and handles them. + """ + raise NotImplementedError("You must implement application_send()") + + ### Application instance management + + def get_or_create_application_instance(self, scope_id, scope): + """ + Creates an application instance and returns its queue. + """ + if scope_id in self.application_instances: + self.application_instances[scope_id]["last_used"] = time.time() + return self.application_instances[scope_id]["input_queue"] + # See if we need to delete an old one + while len(self.application_instances) > self.max_applications: + self.delete_oldest_application_instance() + # Make an instance of the application + input_queue = asyncio.Queue() + application_instance = guarantee_single_callable(self.application) + # Run it, and stash the future for later checking + future = asyncio.ensure_future( + application_instance( + scope=scope, + receive=input_queue.get, + send=lambda message: self.application_send(scope, message), + ), + ) + self.application_instances[scope_id] = { + "input_queue": input_queue, + "future": future, + "scope": scope, + "last_used": time.time(), + } + return input_queue + + def delete_oldest_application_instance(self): + """ + Finds and deletes the oldest application instance + """ + oldest_time = min( + details["last_used"] for details in self.application_instances.values() + ) + for scope_id, details in self.application_instances.items(): + if details["last_used"] == oldest_time: + self.delete_application_instance(scope_id) + # Return to make sure we only delete one in case two have + # the same oldest time + return + + def delete_application_instance(self, scope_id): + """ + Removes an application instance (makes sure its task is stopped, + then removes it from the current set) + """ + details = self.application_instances[scope_id] + del self.application_instances[scope_id] + if not details["future"].done(): + details["future"].cancel() + + async def application_checker(self): + """ + Goes through the set of current application instance Futures and cleans up + any that are done/prints exceptions for any that errored. + """ + while True: + await asyncio.sleep(self.application_checker_interval) + for scope_id, details in list(self.application_instances.items()): + if details["future"].done(): + exception = details["future"].exception() + if exception: + await self.application_exception(exception, details) + try: + del self.application_instances[scope_id] + except KeyError: + # Exception handling might have already got here before us. That's fine. + pass + + async def application_exception(self, exception, application_details): + """ + Called whenever an application coroutine has an exception. + """ + logging.error( + "Exception inside application: %s\n%s%s", + exception, + "".join(traceback.format_tb(exception.__traceback__)), + f" {exception}", + ) diff --git a/venv/Lib/site-packages/asgiref/sync.py b/venv/Lib/site-packages/asgiref/sync.py new file mode 100644 index 0000000..4427fc2 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/sync.py @@ -0,0 +1,613 @@ +import asyncio +import asyncio.coroutines +import contextvars +import functools +import inspect +import os +import sys +import threading +import warnings +import weakref +from concurrent.futures import Future, ThreadPoolExecutor +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Callable, + Coroutine, + Dict, + Generic, + List, + Optional, + TypeVar, + Union, + overload, +) + +from .current_thread_executor import CurrentThreadExecutor +from .local import Local + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if TYPE_CHECKING: + # This is not available to import at runtime + from _typeshed import OptExcInfo + +_F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") +_R = TypeVar("_R") + + +def _restore_context(context: contextvars.Context) -> None: + # Check for changes in contextvars, and set them to the current + # context for downstream consumers + for cvar in context: + cvalue = context.get(cvar) + try: + if cvar.get() != cvalue: + cvar.set(cvalue) + except LookupError: + cvar.set(cvalue) + + +# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for +# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker. +# The latter is replaced with the inspect.markcoroutinefunction decorator. +# Until 3.12 is the minimum supported Python version, provide a shim. + +if hasattr(inspect, "markcoroutinefunction"): + iscoroutinefunction = inspect.iscoroutinefunction + markcoroutinefunction: Callable[[_F], _F] = inspect.markcoroutinefunction +else: + iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment] + + def markcoroutinefunction(func: _F) -> _F: + func._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore + return func + + +class ThreadSensitiveContext: + """Async context manager to manage context for thread sensitive mode + + This context manager controls which thread pool executor is used when in + thread sensitive mode. By default, a single thread pool executor is shared + within a process. + + The ThreadSensitiveContext() context manager may be used to specify a + thread pool per context. + + This context manager is re-entrant, so only the outer-most call to + ThreadSensitiveContext will set the context. + + Usage: + + >>> import time + >>> async with ThreadSensitiveContext(): + ... await sync_to_async(time.sleep, 1)() + """ + + def __init__(self): + self.token = None + + async def __aenter__(self): + try: + SyncToAsync.thread_sensitive_context.get() + except LookupError: + self.token = SyncToAsync.thread_sensitive_context.set(self) + + return self + + async def __aexit__(self, exc, value, tb): + if not self.token: + return + + executor = SyncToAsync.context_to_thread_executor.pop(self, None) + if executor: + executor.shutdown() + SyncToAsync.thread_sensitive_context.reset(self.token) + + +class AsyncToSync(Generic[_P, _R]): + """ + Utility class which turns an awaitable that only works on the thread with + the event loop into a synchronous callable that works in a subthread. + + If the call stack contains an async loop, the code runs there. + Otherwise, the code runs in a new loop in a new thread. + + Either way, this thread then pauses and waits to run any thread_sensitive + code called from further down the call stack using SyncToAsync, before + finally exiting once the async task returns. + """ + + # Keeps a reference to the CurrentThreadExecutor in local context, so that + # any sync_to_async inside the wrapped code can find it. + executors: "Local" = Local() + + # When we can't find a CurrentThreadExecutor from the context, such as + # inside create_task, we'll look it up here from the running event loop. + loop_thread_executors: "Dict[asyncio.AbstractEventLoop, CurrentThreadExecutor]" = {} + + def __init__( + self, + awaitable: Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ], + force_new_loop: bool = False, + ): + if not callable(awaitable) or ( + not iscoroutinefunction(awaitable) + and not iscoroutinefunction(getattr(awaitable, "__call__", awaitable)) + ): + # Python does not have very reliable detection of async functions + # (lots of false negatives) so this is just a warning. + warnings.warn( + "async_to_sync was passed a non-async-marked callable", stacklevel=2 + ) + self.awaitable = awaitable + try: + self.__self__ = self.awaitable.__self__ # type: ignore[union-attr] + except AttributeError: + pass + self.force_new_loop = force_new_loop + self.main_event_loop = None + try: + self.main_event_loop = asyncio.get_running_loop() + except RuntimeError: + # There's no event loop in this thread. + pass + + def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R: + __traceback_hide__ = True # noqa: F841 + + if not self.force_new_loop and not self.main_event_loop: + # There's no event loop in this thread. Look for the threadlocal if + # we're inside SyncToAsync + main_event_loop_pid = getattr( + SyncToAsync.threadlocal, "main_event_loop_pid", None + ) + # We make sure the parent loop is from the same process - if + # they've forked, this is not going to be valid any more (#194) + if main_event_loop_pid and main_event_loop_pid == os.getpid(): + self.main_event_loop = getattr( + SyncToAsync.threadlocal, "main_event_loop", None + ) + + # You can't call AsyncToSync from a thread with a running event loop + try: + event_loop = asyncio.get_running_loop() + except RuntimeError: + pass + else: + if event_loop.is_running(): + raise RuntimeError( + "You cannot use AsyncToSync in the same thread as an async event loop - " + "just await the async function directly." + ) + + # Make a future for the return information + call_result: "Future[_R]" = Future() + + # Make a CurrentThreadExecutor we'll use to idle in this thread - we + # need one for every sync frame, even if there's one above us in the + # same thread. + old_executor = getattr(self.executors, "current", None) + current_executor = CurrentThreadExecutor() + self.executors.current = current_executor + + # Wrapping context in list so it can be reassigned from within + # `main_wrap`. + context = [contextvars.copy_context()] + + # Get task context so that parent task knows which task to propagate + # an asyncio.CancelledError to. + task_context = getattr(SyncToAsync.threadlocal, "task_context", None) + + loop = None + # Use call_soon_threadsafe to schedule a synchronous callback on the + # main event loop's thread if it's there, otherwise make a new loop + # in this thread. + try: + awaitable = self.main_wrap( + call_result, + sys.exc_info(), + task_context, + context, + *args, + **kwargs, + ) + + if not (self.main_event_loop and self.main_event_loop.is_running()): + # Make our own event loop - in a new thread - and run inside that. + loop = asyncio.new_event_loop() + self.loop_thread_executors[loop] = current_executor + loop_executor = ThreadPoolExecutor(max_workers=1) + loop_future = loop_executor.submit( + self._run_event_loop, loop, awaitable + ) + if current_executor: + # Run the CurrentThreadExecutor until the future is done + current_executor.run_until_future(loop_future) + # Wait for future and/or allow for exception propagation + loop_future.result() + else: + # Call it inside the existing loop + self.main_event_loop.call_soon_threadsafe( + self.main_event_loop.create_task, awaitable + ) + if current_executor: + # Run the CurrentThreadExecutor until the future is done + current_executor.run_until_future(call_result) + finally: + # Clean up any executor we were running + if loop is not None: + del self.loop_thread_executors[loop] + _restore_context(context[0]) + # Restore old current thread executor state + self.executors.current = old_executor + + # Wait for results from the future. + return call_result.result() + + def _run_event_loop(self, loop, coro): + """ + Runs the given event loop (designed to be called in a thread). + """ + asyncio.set_event_loop(loop) + try: + loop.run_until_complete(coro) + finally: + try: + # mimic asyncio.run() behavior + # cancel unexhausted async generators + tasks = asyncio.all_tasks(loop) + for task in tasks: + task.cancel() + + async def gather(): + await asyncio.gather(*tasks, return_exceptions=True) + + loop.run_until_complete(gather()) + for task in tasks: + if task.cancelled(): + continue + if task.exception() is not None: + loop.call_exception_handler( + { + "message": "unhandled exception during loop shutdown", + "exception": task.exception(), + "task": task, + } + ) + if hasattr(loop, "shutdown_asyncgens"): + loop.run_until_complete(loop.shutdown_asyncgens()) + finally: + loop.close() + asyncio.set_event_loop(self.main_event_loop) + + def __get__(self, parent: Any, objtype: Any) -> Callable[_P, _R]: + """ + Include self for methods + """ + func = functools.partial(self.__call__, parent) + return functools.update_wrapper(func, self.awaitable) + + async def main_wrap( + self, + call_result: "Future[_R]", + exc_info: "OptExcInfo", + task_context: "Optional[List[asyncio.Task[Any]]]", + context: List[contextvars.Context], + *args: _P.args, + **kwargs: _P.kwargs, + ) -> None: + """ + Wraps the awaitable with something that puts the result into the + result/exception future. + """ + + __traceback_hide__ = True # noqa: F841 + + if context is not None: + _restore_context(context[0]) + + current_task = asyncio.current_task() + if current_task is not None and task_context is not None: + task_context.append(current_task) + + try: + # If we have an exception, run the function inside the except block + # after raising it so exc_info is correctly populated. + if exc_info[1]: + try: + raise exc_info[1] + except BaseException: + result = await self.awaitable(*args, **kwargs) + else: + result = await self.awaitable(*args, **kwargs) + except BaseException as e: + call_result.set_exception(e) + else: + call_result.set_result(result) + finally: + if current_task is not None and task_context is not None: + task_context.remove(current_task) + context[0] = contextvars.copy_context() + + +class SyncToAsync(Generic[_P, _R]): + """ + Utility class which turns a synchronous callable into an awaitable that + runs in a threadpool. It also sets a threadlocal inside the thread so + calls to AsyncToSync can escape it. + + If thread_sensitive is passed, the code will run in the same thread as any + outer code. This is needed for underlying Python code that is not + threadsafe (for example, code which handles SQLite database connections). + + If the outermost program is async (i.e. SyncToAsync is outermost), then + this will be a dedicated single sub-thread that all sync code runs in, + one after the other. If the outermost program is sync (i.e. AsyncToSync is + outermost), this will just be the main thread. This is achieved by idling + with a CurrentThreadExecutor while AsyncToSync is blocking its sync parent, + rather than just blocking. + + If executor is passed in, that will be used instead of the loop's default executor. + In order to pass in an executor, thread_sensitive must be set to False, otherwise + a TypeError will be raised. + """ + + # Storage for main event loop references + threadlocal = threading.local() + + # Single-thread executor for thread-sensitive code + single_thread_executor = ThreadPoolExecutor(max_workers=1) + + # Maintain a contextvar for the current execution context. Optionally used + # for thread sensitive mode. + thread_sensitive_context: "contextvars.ContextVar[ThreadSensitiveContext]" = ( + contextvars.ContextVar("thread_sensitive_context") + ) + + # Contextvar that is used to detect if the single thread executor + # would be awaited on while already being used in the same context + deadlock_context: "contextvars.ContextVar[bool]" = contextvars.ContextVar( + "deadlock_context" + ) + + # Maintaining a weak reference to the context ensures that thread pools are + # erased once the context goes out of scope. This terminates the thread pool. + context_to_thread_executor: "weakref.WeakKeyDictionary[ThreadSensitiveContext, ThreadPoolExecutor]" = ( + weakref.WeakKeyDictionary() + ) + + def __init__( + self, + func: Callable[_P, _R], + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, + ) -> None: + if ( + not callable(func) + or iscoroutinefunction(func) + or iscoroutinefunction(getattr(func, "__call__", func)) + ): + raise TypeError("sync_to_async can only be applied to sync functions.") + self.func = func + functools.update_wrapper(self, func) + self._thread_sensitive = thread_sensitive + markcoroutinefunction(self) + if thread_sensitive and executor is not None: + raise TypeError("executor must not be set when thread_sensitive is True") + self._executor = executor + try: + self.__self__ = func.__self__ # type: ignore + except AttributeError: + pass + + async def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R: + __traceback_hide__ = True # noqa: F841 + loop = asyncio.get_running_loop() + + # Work out what thread to run the code in + if self._thread_sensitive: + current_thread_executor = getattr(AsyncToSync.executors, "current", None) + if current_thread_executor: + # If we have a parent sync thread above somewhere, use that + executor = current_thread_executor + elif self.thread_sensitive_context.get(None): + # If we have a way of retrieving the current context, attempt + # to use a per-context thread pool executor + thread_sensitive_context = self.thread_sensitive_context.get() + + if thread_sensitive_context in self.context_to_thread_executor: + # Re-use thread executor in current context + executor = self.context_to_thread_executor[thread_sensitive_context] + else: + # Create new thread executor in current context + executor = ThreadPoolExecutor(max_workers=1) + self.context_to_thread_executor[thread_sensitive_context] = executor + elif loop in AsyncToSync.loop_thread_executors: + # Re-use thread executor for running loop + executor = AsyncToSync.loop_thread_executors[loop] + elif self.deadlock_context.get(False): + raise RuntimeError( + "Single thread executor already being used, would deadlock" + ) + else: + # Otherwise, we run it in a fixed single thread + executor = self.single_thread_executor + self.deadlock_context.set(True) + else: + # Use the passed in executor, or the loop's default if it is None + executor = self._executor + + context = contextvars.copy_context() + child = functools.partial(self.func, *args, **kwargs) + func = context.run + task_context: List[asyncio.Task[Any]] = [] + + # Run the code in the right thread + exec_coro = loop.run_in_executor( + executor, + functools.partial( + self.thread_handler, + loop, + sys.exc_info(), + task_context, + func, + child, + ), + ) + ret: _R + try: + ret = await asyncio.shield(exec_coro) + except asyncio.CancelledError: + cancel_parent = True + try: + task = task_context[0] + task.cancel() + try: + await task + cancel_parent = False + except asyncio.CancelledError: + pass + except IndexError: + pass + if exec_coro.done(): + raise + if cancel_parent: + exec_coro.cancel() + ret = await exec_coro + finally: + _restore_context(context) + self.deadlock_context.set(False) + + return ret + + def __get__( + self, parent: Any, objtype: Any + ) -> Callable[_P, Coroutine[Any, Any, _R]]: + """ + Include self for methods + """ + func = functools.partial(self.__call__, parent) + return functools.update_wrapper(func, self.func) + + def thread_handler(self, loop, exc_info, task_context, func, *args, **kwargs): + """ + Wraps the sync application with exception handling. + """ + + __traceback_hide__ = True # noqa: F841 + + # Set the threadlocal for AsyncToSync + self.threadlocal.main_event_loop = loop + self.threadlocal.main_event_loop_pid = os.getpid() + self.threadlocal.task_context = task_context + + # Run the function + # If we have an exception, run the function inside the except block + # after raising it so exc_info is correctly populated. + if exc_info[1]: + try: + raise exc_info[1] + except BaseException: + return func(*args, **kwargs) + else: + return func(*args, **kwargs) + + +@overload +def async_to_sync( + *, + force_new_loop: bool = False, +) -> Callable[ + [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, Awaitable[_R]]]], + Callable[_P, _R], +]: + ... + + +@overload +def async_to_sync( + awaitable: Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ], + *, + force_new_loop: bool = False, +) -> Callable[_P, _R]: + ... + + +def async_to_sync( + awaitable: Optional[ + Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ] + ] = None, + *, + force_new_loop: bool = False, +) -> Union[ + Callable[ + [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, Awaitable[_R]]]], + Callable[_P, _R], + ], + Callable[_P, _R], +]: + if awaitable is None: + return lambda f: AsyncToSync( + f, + force_new_loop=force_new_loop, + ) + return AsyncToSync( + awaitable, + force_new_loop=force_new_loop, + ) + + +@overload +def sync_to_async( + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, +) -> Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]]: + ... + + +@overload +def sync_to_async( + func: Callable[_P, _R], + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, +) -> Callable[_P, Coroutine[Any, Any, _R]]: + ... + + +def sync_to_async( + func: Optional[Callable[_P, _R]] = None, + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, +) -> Union[ + Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]], + Callable[_P, Coroutine[Any, Any, _R]], +]: + if func is None: + return lambda f: SyncToAsync( + f, + thread_sensitive=thread_sensitive, + executor=executor, + ) + return SyncToAsync( + func, + thread_sensitive=thread_sensitive, + executor=executor, + ) diff --git a/venv/Lib/site-packages/asgiref/testing.py b/venv/Lib/site-packages/asgiref/testing.py new file mode 100644 index 0000000..aa7cff1 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/testing.py @@ -0,0 +1,103 @@ +import asyncio +import contextvars +import time + +from .compatibility import guarantee_single_callable +from .timeout import timeout as async_timeout + + +class ApplicationCommunicator: + """ + Runs an ASGI application in a test mode, allowing sending of + messages to it and retrieval of messages it sends. + """ + + def __init__(self, application, scope): + self.application = guarantee_single_callable(application) + self.scope = scope + self.input_queue = asyncio.Queue() + self.output_queue = asyncio.Queue() + # Clear context - this ensures that context vars set in the testing scope + # are not "leaked" into the application which would normally begin with + # an empty context. In Python >= 3.11 this could also be written as: + # asyncio.create_task(..., context=contextvars.Context()) + self.future = contextvars.Context().run( + asyncio.create_task, + self.application(scope, self.input_queue.get, self.output_queue.put), + ) + + async def wait(self, timeout=1): + """ + Waits for the application to stop itself and returns any exceptions. + """ + try: + async with async_timeout(timeout): + try: + await self.future + self.future.result() + except asyncio.CancelledError: + pass + finally: + if not self.future.done(): + self.future.cancel() + try: + await self.future + except asyncio.CancelledError: + pass + + def stop(self, exceptions=True): + if not self.future.done(): + self.future.cancel() + elif exceptions: + # Give a chance to raise any exceptions + self.future.result() + + def __del__(self): + # Clean up on deletion + try: + self.stop(exceptions=False) + except RuntimeError: + # Event loop already stopped + pass + + async def send_input(self, message): + """ + Sends a single message to the application + """ + # Give it the message + await self.input_queue.put(message) + + async def receive_output(self, timeout=1): + """ + Receives a single message from the application, with optional timeout. + """ + # Make sure there's not an exception to raise from the task + if self.future.done(): + self.future.result() + # Wait and receive the message + try: + async with async_timeout(timeout): + return await self.output_queue.get() + except asyncio.TimeoutError as e: + # See if we have another error to raise inside + if self.future.done(): + self.future.result() + else: + self.future.cancel() + try: + await self.future + except asyncio.CancelledError: + pass + raise e + + async def receive_nothing(self, timeout=0.1, interval=0.01): + """ + Checks that there is no message to receive in the given time. + """ + # `interval` has precedence over `timeout` + start = time.monotonic() + while time.monotonic() - start < timeout: + if not self.output_queue.empty(): + return False + await asyncio.sleep(interval) + return self.output_queue.empty() diff --git a/venv/Lib/site-packages/asgiref/timeout.py b/venv/Lib/site-packages/asgiref/timeout.py new file mode 100644 index 0000000..fd5381d --- /dev/null +++ b/venv/Lib/site-packages/asgiref/timeout.py @@ -0,0 +1,118 @@ +# This code is originally sourced from the aio-libs project "async_timeout", +# under the Apache 2.0 license. You may see the original project at +# https://github.com/aio-libs/async-timeout + +# It is vendored here to reduce chain-dependencies on this library, and +# modified slightly to remove some features we don't use. + + +import asyncio +import warnings +from types import TracebackType +from typing import Any # noqa +from typing import Optional, Type + + +class timeout: + """timeout context manager. + + Useful in cases when you want to apply timeout logic around block + of code or in cases when asyncio.wait_for is not suitable. For example: + + >>> with timeout(0.001): + ... async with aiohttp.get('https://github.com') as r: + ... await r.text() + + + timeout - value in seconds or None to disable timeout logic + loop - asyncio compatible event loop + """ + + def __init__( + self, + timeout: Optional[float], + *, + loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + self._timeout = timeout + if loop is None: + loop = asyncio.get_running_loop() + else: + warnings.warn( + """The loop argument to timeout() is deprecated.""", DeprecationWarning + ) + self._loop = loop + self._task = None # type: Optional[asyncio.Task[Any]] + self._cancelled = False + self._cancel_handler = None # type: Optional[asyncio.Handle] + self._cancel_at = None # type: Optional[float] + + def __enter__(self) -> "timeout": + return self._do_enter() + + def __exit__( + self, + exc_type: Type[BaseException], + exc_val: BaseException, + exc_tb: TracebackType, + ) -> Optional[bool]: + self._do_exit(exc_type) + return None + + async def __aenter__(self) -> "timeout": + return self._do_enter() + + async def __aexit__( + self, + exc_type: Type[BaseException], + exc_val: BaseException, + exc_tb: TracebackType, + ) -> None: + self._do_exit(exc_type) + + @property + def expired(self) -> bool: + return self._cancelled + + @property + def remaining(self) -> Optional[float]: + if self._cancel_at is not None: + return max(self._cancel_at - self._loop.time(), 0.0) + else: + return None + + def _do_enter(self) -> "timeout": + # Support Tornado 5- without timeout + # Details: https://github.com/python/asyncio/issues/392 + if self._timeout is None: + return self + + self._task = asyncio.current_task(self._loop) + if self._task is None: + raise RuntimeError( + "Timeout context manager should be used " "inside a task" + ) + + if self._timeout <= 0: + self._loop.call_soon(self._cancel_task) + return self + + self._cancel_at = self._loop.time() + self._timeout + self._cancel_handler = self._loop.call_at(self._cancel_at, self._cancel_task) + return self + + def _do_exit(self, exc_type: Type[BaseException]) -> None: + if exc_type is asyncio.CancelledError and self._cancelled: + self._cancel_handler = None + self._task = None + raise asyncio.TimeoutError + if self._timeout is not None and self._cancel_handler is not None: + self._cancel_handler.cancel() + self._cancel_handler = None + self._task = None + return None + + def _cancel_task(self) -> None: + if self._task is not None: + self._task.cancel() + self._cancelled = True diff --git a/venv/Lib/site-packages/asgiref/typing.py b/venv/Lib/site-packages/asgiref/typing.py new file mode 100644 index 0000000..71c25ed --- /dev/null +++ b/venv/Lib/site-packages/asgiref/typing.py @@ -0,0 +1,278 @@ +import sys +from typing import ( + Any, + Awaitable, + Callable, + Dict, + Iterable, + Literal, + Optional, + Protocol, + Tuple, + Type, + TypedDict, + Union, +) + +if sys.version_info >= (3, 11): + from typing import NotRequired +else: + from typing_extensions import NotRequired + +__all__ = ( + "ASGIVersions", + "HTTPScope", + "WebSocketScope", + "LifespanScope", + "WWWScope", + "Scope", + "HTTPRequestEvent", + "HTTPResponseStartEvent", + "HTTPResponseBodyEvent", + "HTTPResponseTrailersEvent", + "HTTPResponsePathsendEvent", + "HTTPServerPushEvent", + "HTTPDisconnectEvent", + "WebSocketConnectEvent", + "WebSocketAcceptEvent", + "WebSocketReceiveEvent", + "WebSocketSendEvent", + "WebSocketResponseStartEvent", + "WebSocketResponseBodyEvent", + "WebSocketDisconnectEvent", + "WebSocketCloseEvent", + "LifespanStartupEvent", + "LifespanShutdownEvent", + "LifespanStartupCompleteEvent", + "LifespanStartupFailedEvent", + "LifespanShutdownCompleteEvent", + "LifespanShutdownFailedEvent", + "ASGIReceiveEvent", + "ASGISendEvent", + "ASGIReceiveCallable", + "ASGISendCallable", + "ASGI2Protocol", + "ASGI2Application", + "ASGI3Application", + "ASGIApplication", +) + + +class ASGIVersions(TypedDict): + spec_version: str + version: Union[Literal["2.0"], Literal["3.0"]] + + +class HTTPScope(TypedDict): + type: Literal["http"] + asgi: ASGIVersions + http_version: str + method: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + state: NotRequired[Dict[str, Any]] + extensions: Optional[Dict[str, Dict[object, object]]] + + +class WebSocketScope(TypedDict): + type: Literal["websocket"] + asgi: ASGIVersions + http_version: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + subprotocols: Iterable[str] + state: NotRequired[Dict[str, Any]] + extensions: Optional[Dict[str, Dict[object, object]]] + + +class LifespanScope(TypedDict): + type: Literal["lifespan"] + asgi: ASGIVersions + state: NotRequired[Dict[str, Any]] + + +WWWScope = Union[HTTPScope, WebSocketScope] +Scope = Union[HTTPScope, WebSocketScope, LifespanScope] + + +class HTTPRequestEvent(TypedDict): + type: Literal["http.request"] + body: bytes + more_body: bool + + +class HTTPResponseDebugEvent(TypedDict): + type: Literal["http.response.debug"] + info: Dict[str, object] + + +class HTTPResponseStartEvent(TypedDict): + type: Literal["http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + trailers: bool + + +class HTTPResponseBodyEvent(TypedDict): + type: Literal["http.response.body"] + body: bytes + more_body: bool + + +class HTTPResponseTrailersEvent(TypedDict): + type: Literal["http.response.trailers"] + headers: Iterable[Tuple[bytes, bytes]] + more_trailers: bool + + +class HTTPResponsePathsendEvent(TypedDict): + type: Literal["http.response.pathsend"] + path: str + + +class HTTPServerPushEvent(TypedDict): + type: Literal["http.response.push"] + path: str + headers: Iterable[Tuple[bytes, bytes]] + + +class HTTPDisconnectEvent(TypedDict): + type: Literal["http.disconnect"] + + +class WebSocketConnectEvent(TypedDict): + type: Literal["websocket.connect"] + + +class WebSocketAcceptEvent(TypedDict): + type: Literal["websocket.accept"] + subprotocol: Optional[str] + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketReceiveEvent(TypedDict): + type: Literal["websocket.receive"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketSendEvent(TypedDict): + type: Literal["websocket.send"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketResponseStartEvent(TypedDict): + type: Literal["websocket.http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketResponseBodyEvent(TypedDict): + type: Literal["websocket.http.response.body"] + body: bytes + more_body: bool + + +class WebSocketDisconnectEvent(TypedDict): + type: Literal["websocket.disconnect"] + code: int + + +class WebSocketCloseEvent(TypedDict): + type: Literal["websocket.close"] + code: int + reason: Optional[str] + + +class LifespanStartupEvent(TypedDict): + type: Literal["lifespan.startup"] + + +class LifespanShutdownEvent(TypedDict): + type: Literal["lifespan.shutdown"] + + +class LifespanStartupCompleteEvent(TypedDict): + type: Literal["lifespan.startup.complete"] + + +class LifespanStartupFailedEvent(TypedDict): + type: Literal["lifespan.startup.failed"] + message: str + + +class LifespanShutdownCompleteEvent(TypedDict): + type: Literal["lifespan.shutdown.complete"] + + +class LifespanShutdownFailedEvent(TypedDict): + type: Literal["lifespan.shutdown.failed"] + message: str + + +ASGIReceiveEvent = Union[ + HTTPRequestEvent, + HTTPDisconnectEvent, + WebSocketConnectEvent, + WebSocketReceiveEvent, + WebSocketDisconnectEvent, + LifespanStartupEvent, + LifespanShutdownEvent, +] + + +ASGISendEvent = Union[ + HTTPResponseStartEvent, + HTTPResponseBodyEvent, + HTTPResponseTrailersEvent, + HTTPServerPushEvent, + HTTPDisconnectEvent, + WebSocketAcceptEvent, + WebSocketSendEvent, + WebSocketResponseStartEvent, + WebSocketResponseBodyEvent, + WebSocketCloseEvent, + LifespanStartupCompleteEvent, + LifespanStartupFailedEvent, + LifespanShutdownCompleteEvent, + LifespanShutdownFailedEvent, +] + + +ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]] +ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]] + + +class ASGI2Protocol(Protocol): + def __init__(self, scope: Scope) -> None: + ... + + async def __call__( + self, receive: ASGIReceiveCallable, send: ASGISendCallable + ) -> None: + ... + + +ASGI2Application = Type[ASGI2Protocol] +ASGI3Application = Callable[ + [ + Scope, + ASGIReceiveCallable, + ASGISendCallable, + ], + Awaitable[None], +] +ASGIApplication = Union[ASGI2Application, ASGI3Application] diff --git a/venv/Lib/site-packages/asgiref/wsgi.py b/venv/Lib/site-packages/asgiref/wsgi.py new file mode 100644 index 0000000..65af427 --- /dev/null +++ b/venv/Lib/site-packages/asgiref/wsgi.py @@ -0,0 +1,166 @@ +from io import BytesIO +from tempfile import SpooledTemporaryFile + +from asgiref.sync import AsyncToSync, sync_to_async + + +class WsgiToAsgi: + """ + Wraps a WSGI application to make it into an ASGI application. + """ + + def __init__(self, wsgi_application): + self.wsgi_application = wsgi_application + + async def __call__(self, scope, receive, send): + """ + ASGI application instantiation point. + We return a new WsgiToAsgiInstance here with the WSGI app + and the scope, ready to respond when it is __call__ed. + """ + await WsgiToAsgiInstance(self.wsgi_application)(scope, receive, send) + + +class WsgiToAsgiInstance: + """ + Per-socket instance of a wrapped WSGI application + """ + + def __init__(self, wsgi_application): + self.wsgi_application = wsgi_application + self.response_started = False + self.response_content_length = None + + async def __call__(self, scope, receive, send): + if scope["type"] != "http": + raise ValueError("WSGI wrapper received a non-HTTP scope") + self.scope = scope + with SpooledTemporaryFile(max_size=65536) as body: + # Alright, wait for the http.request messages + while True: + message = await receive() + if message["type"] != "http.request": + raise ValueError("WSGI wrapper received a non-HTTP-request message") + body.write(message.get("body", b"")) + if not message.get("more_body"): + break + body.seek(0) + # Wrap send so it can be called from the subthread + self.sync_send = AsyncToSync(send) + # Call the WSGI app + await self.run_wsgi_app(body) + + def build_environ(self, scope, body): + """ + Builds a scope and request body into a WSGI environ object. + """ + script_name = scope.get("root_path", "").encode("utf8").decode("latin1") + path_info = scope["path"].encode("utf8").decode("latin1") + if path_info.startswith(script_name): + path_info = path_info[len(script_name) :] + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": script_name, + "PATH_INFO": path_info, + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": body, + "wsgi.errors": BytesIO(), + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + # Get server name and port - required in WSGI, not in ASGI + if "server" in scope: + environ["SERVER_NAME"] = scope["server"][0] + environ["SERVER_PORT"] = str(scope["server"][1]) + else: + environ["SERVER_NAME"] = "localhost" + environ["SERVER_PORT"] = "80" + + if scope.get("client") is not None: + environ["REMOTE_ADDR"] = scope["client"][0] + + # Go through headers and make them into environ entries + for name, value in self.scope.get("headers", []): + name = name.decode("latin1") + if name == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = "HTTP_%s" % name.upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in case + value = value.decode("latin1") + if corrected_name in environ: + value = environ[corrected_name] + "," + value + environ[corrected_name] = value + return environ + + def start_response(self, status, response_headers, exc_info=None): + """ + WSGI start_response callable. + """ + # Don't allow re-calling once response has begun + if self.response_started: + raise exc_info[1].with_traceback(exc_info[2]) + # Don't allow re-calling without exc_info + if hasattr(self, "response_start") and exc_info is None: + raise ValueError( + "You cannot call start_response a second time without exc_info" + ) + # Extract status code + status_code, _ = status.split(" ", 1) + status_code = int(status_code) + # Extract headers + headers = [ + (name.lower().encode("ascii"), value.encode("ascii")) + for name, value in response_headers + ] + # Extract content-length + self.response_content_length = None + for name, value in response_headers: + if name.lower() == "content-length": + self.response_content_length = int(value) + # Build and send response start message. + self.response_start = { + "type": "http.response.start", + "status": status_code, + "headers": headers, + } + + @sync_to_async + def run_wsgi_app(self, body): + """ + Called in a subthread to run the WSGI app. We encapsulate like + this so that the start_response callable is called in the same thread. + """ + # Translate the scope and incoming request body into a WSGI environ + environ = self.build_environ(self.scope, body) + # Run the WSGI app + bytes_sent = 0 + for output in self.wsgi_application(environ, self.start_response): + # If this is the first response, include the response headers + if not self.response_started: + self.response_started = True + self.sync_send(self.response_start) + # If the application supplies a Content-Length header + if self.response_content_length is not None: + # The server should not transmit more bytes to the client than the header allows + bytes_allowed = self.response_content_length - bytes_sent + if len(output) > bytes_allowed: + output = output[:bytes_allowed] + self.sync_send( + {"type": "http.response.body", "body": output, "more_body": True} + ) + bytes_sent += len(output) + # The server should stop iterating over the response when enough data has been sent + if bytes_sent == self.response_content_length: + break + # Close connection + if not self.response_started: + self.response_started = True + self.sync_send(self.response_start) + self.sync_send({"type": "http.response.body"}) diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/AUTHORS.txt b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/AUTHORS.txt new file mode 100644 index 0000000..ae94c4e --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/AUTHORS.txt @@ -0,0 +1,5 @@ +The authors in alphabetical order + +* Charlie Clark +* Daniel Hillier +* Elias Rabel diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/INSTALLER b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.python b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.python new file mode 100644 index 0000000..3740f80 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.python @@ -0,0 +1,298 @@ +et_xml is licensed under the MIT license; see the file LICENCE for details. + +et_xml includes code from the Python standard library, which is licensed under +the Python license, a permissive open source license. The copyright and license +is included below for compliance with Python's terms. + +This module includes corrections and new features as follows: +- Correct handling of attributes namespaces when a default namespace + has been registered. +- Records the namespaces for an Element during parsing and utilises them to + allow inspection of namespaces at specific elements in the xml tree and + during serialisation. + +Misc: +- Includes the test_xml_etree with small modifications for testing the + modifications in this package. + +---------------------------------------------------------------------- + +Copyright (c) 2001-present Python Software Foundation; All Rights Reserved + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001-2024 Python Software Foundation; All Rights Reserved" +are retained in Python alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.rst b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.rst new file mode 100644 index 0000000..82213c5 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/LICENCE.rst @@ -0,0 +1,23 @@ +This software is under the MIT Licence +====================================== + +Copyright (c) 2010 openpyxl + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/METADATA b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/METADATA new file mode 100644 index 0000000..3eee724 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/METADATA @@ -0,0 +1,51 @@ +Metadata-Version: 2.1 +Name: et_xmlfile +Version: 2.0.0 +Summary: An implementation of lxml.xmlfile for the standard library +Home-page: https://foss.heptapod.net/openpyxl/et_xmlfile +Author: See AUTHORS.txt +Author-email: charlie.clark@clark-consulting.eu +License: MIT +Project-URL: Documentation, https://openpyxl.pages.heptapod.net/et_xmlfile/ +Project-URL: Source, https://foss.heptapod.net/openpyxl/et_xmlfile +Project-URL: Tracker, https://foss.heptapod.net/openpyxl/et_xmfile/-/issues +Classifier: Development Status :: 5 - Production/Stable +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Requires-Python: >=3.8 +License-File: LICENCE.python +License-File: LICENCE.rst +License-File: AUTHORS.txt + +.. image:: https://foss.heptapod.net/openpyxl/et_xmlfile/badges/branch/default/coverage.svg + :target: https://coveralls.io/bitbucket/openpyxl/et_xmlfile?branch=default + :alt: coverage status + +et_xmfile +========= + +XML can use lots of memory, and et_xmlfile is a low memory library for creating large XML files +And, although the standard library already includes an incremental parser, `iterparse` it has no equivalent when writing XML. Once an element has been added to the tree, it is written to +the file or stream and the memory is then cleared. + +This module is based upon the `xmlfile module from lxml `_ with the aim of allowing code to be developed that will work with both libraries. +It was developed initially for the openpyxl project, but is now a standalone module. + +The code was written by Elias Rabel as part of the `Python Düsseldorf `_ openpyxl sprint in September 2014. + +Proper support for incremental writing was provided by Daniel Hillier in 2024 + +Note on performance +------------------- + +The code was not developed with performance in mind, but turned out to be faster than the existing SAX-based implementation but is generally slower than lxml's xmlfile. +There is one area where an optimisation for lxml may negatively affect the performance of et_xmfile and that is when using the `.element()` method on the xmlfile context manager. It is, therefore, recommended simply to create Elements write these directly, as in the sample code. diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/RECORD b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/RECORD new file mode 100644 index 0000000..0d9cce2 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/RECORD @@ -0,0 +1,14 @@ +et_xmlfile-2.0.0.dist-info/AUTHORS.txt,sha256=fwOAKepUY2Bd0ieNMACZo4G86ekN2oPMqyBCNGtsgQc,82 +et_xmlfile-2.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +et_xmlfile-2.0.0.dist-info/LICENCE.python,sha256=TM2q68D0S4NyDsA5m7erMprc4GfdYvc8VTWi3AViirI,14688 +et_xmlfile-2.0.0.dist-info/LICENCE.rst,sha256=DIS7QvXTZ-Xr-fwt3jWxYUHfXuD9wYklCFi8bFVg9p4,1131 +et_xmlfile-2.0.0.dist-info/METADATA,sha256=DpfX6pCe0PvgPYi8i29YZ3zuGwe9M1PONhzSQFkVIE4,2711 +et_xmlfile-2.0.0.dist-info/RECORD,, +et_xmlfile-2.0.0.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91 +et_xmlfile-2.0.0.dist-info/top_level.txt,sha256=34-74d5NNARgTsPxCMta5o28XpBNmSN0iCZhtmx2Fk8,11 +et_xmlfile/__init__.py,sha256=AQ4_2cNUEyUHlHo-Y3Gd6-8S_6eyKd55jYO4eh23UHw,228 +et_xmlfile/__pycache__/__init__.cpython-312.pyc,, +et_xmlfile/__pycache__/incremental_tree.cpython-312.pyc,, +et_xmlfile/__pycache__/xmlfile.cpython-312.pyc,, +et_xmlfile/incremental_tree.py,sha256=lX4VStfzUNK0jtrVsvshPENu7E_zQirglkyRtzGDwEg,34534 +et_xmlfile/xmlfile.py,sha256=6QdxBq2P0Cf35R-oyXjLl5wOItfJJ4Yy6AlIF9RX7Bg,4886 diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/WHEEL b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/WHEEL new file mode 100644 index 0000000..71360e0 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (72.2.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/top_level.txt b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/top_level.txt new file mode 100644 index 0000000..f573c27 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile-2.0.0.dist-info/top_level.txt @@ -0,0 +1 @@ +et_xmlfile diff --git a/venv/Lib/site-packages/et_xmlfile/__init__.py b/venv/Lib/site-packages/et_xmlfile/__init__.py new file mode 100644 index 0000000..776a146 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile/__init__.py @@ -0,0 +1,8 @@ +from .xmlfile import xmlfile + +# constants +__version__ = '2.0.0' +__author__ = 'See AUTHORS.txt' +__license__ = 'MIT' +__author_email__ = 'charlie.clark@clark-consulting.eu' +__url__ = 'https://foss.heptapod.net/openpyxl/et_xmlfile' diff --git a/venv/Lib/site-packages/et_xmlfile/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/et_xmlfile/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..847599bad9e47f2f05c19e5bcee46e90cd76f21c GIT binary patch literal 447 zcmYL_J4*vW5P| zAoyEsEW?47Hg@VrZ@HI5)PG?fe|U_6;Zk`DU9 z14Dks9o0+9wHxGBLVBPymkA+xg%FyVNGi)VA$SOh2J6iHB_O6;*hra>Oj&q9ALHXc z&zc)SN83(8TQY`QyUn0Ubx0YUD0vN`(E+1|5+0{g8BjqFl3sAYF9OXCG*TLN=@sbU ze?^ZFo^V45P6zqqW-M7IU`y5PwDIrs_}A~Q<2cV~{=I~z=WeQ_+QLm`G&O5!cI^qx Mj4JE5WmUC>UwUkeEC2ui literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/et_xmlfile/__pycache__/incremental_tree.cpython-312.pyc b/venv/Lib/site-packages/et_xmlfile/__pycache__/incremental_tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ebc8f09e2422169b17de59b3157a8255ebb9f65 GIT binary patch literal 24461 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/et_xmlfile/__pycache__/xmlfile.cpython-312.pyc b/venv/Lib/site-packages/et_xmlfile/__pycache__/xmlfile.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84c2317ec6f3f34994ed0972967edbdb1ce2d7bc GIT binary patch literal 5484 zcmai2U2Gf25#Hn7kw@|NL7nEuwj4*1Qai5D`X@mI71tB*WK-c^ z_l~xyl86x)sB9#)jJA=}w1@))ja{c`+Lyler9g{5)U+M&a!`Q)eQDklQ|aGJJF~|l zC4)kj;OyS+?C#vo>^C#_=TIm>pnUfiXU=tX5b`&CaEn-P)Jo7;BO1}TG|6yt97p{4 z(_hc*u)H^Ij&JPxs&9ofYQ-tXG0wzaDJ# z%B(j4y}>QLp`x4!eU1|ooE=sdj9j{4>Pjk;&ruV)+LF1fsb4fRYF0g~(}c(NO{evY zo;B@|q8mvyuPaGSHPz2KXN^cIo1~0EO)DnV^`s+}Ly-wfO$M??bTY?jWX@CMVBzqI zi<$JPV%AhIPE(qrvkBgo6eX)>bVacPijv7`g*3KhMfqMqO*&)1pzhvTQs+%Crx7><*dJ&PUp|-+4J)!QVa7&%GCGe)#PjNhQ_>Z zDj>&VDy{FY*Aw|7MLjao4h;i!cbQm%M8j_Xw%4p{g4CXc;pS^<+#IiYE|WPy7d1%} zE^~Ka9LtECV;LQE0sK#JSkH4n0|LoiCg3}vE)f{CE)|^hg?|% zX~iwt#ixdLOJu3do!P8um*y>dTaRfzeA9W5pzJG4Wq%g#MA-{6_%yC8LG3s3y0Nmf z%WXAlST)*wa$6;_XFUqY_9FLG=GVEmuP{XZ`q|JE}@-0Qs^Go zwZ#f%zsuNqo@*y=&5*C#I;bntEJ~XY~tlz?OLZF2@T-Dti|C>n9jjI-aNcV(Ox9#4n`Gb8#)TxTxdh zkDobt%s6d(Rnw%Yg_+O)3nd}hK{iP-lDWK2QK@#+I0sHk(KC6o=mLyE(Zp;734|3p zRG=xv%qh-Zc2`{jKo$kpcl-VDZVuWkdk*clxyeM>4!o?U3p#U6wg9^pZ9bpNQ?xUR zYP1D(lt9%~nxb7g7#6vJh|T0dw4)|PjWCHF*}Q5#uV*!i7by{>yKyPrRL{~uY>5u$ zc@6#M8bD_&Rs59lw73M<-UMt)Bk({O|a0j=mdSnO+^fatucM7?fJU_LWJivwLM` zJ>0cwRKf>te*JFvz^#{|wIW#2F2GyATLr__;K04$fYsHv^5RB-w0Bk`BbCU=&F3qT z@h|*BsLhJ>S&^|%BmJ;JH!xYdV=FINdlGl$VJkMU^3BaQ66&wY`zrE2OO9MSe&sk+ zR?mpl+h6V7Tj||v4UJjRp0yL#Pgv1DYxlS{@(k>@*%=H4z6g2!0ZR^Ba<>J`$-S1` zzpe~Yk@0))sr{) z)xwRVs|O!QgH|wn?U}33)P?(T`R3^lUw!}8``!CLkssgSiQM^b11;r^>DcrDx6QAk zx&cc`?QPK78fp5D5@$Ai_?>!-J^|RU)lb1hEJmQ|^C3qFC>}kEe<42iS;mbl<1h2xE(X;X3T?D8_6Qed(mM}1Q zq`;~zq8o^dco=Eng*5DM<%hsKmV}SQJN1(T6crNQ<$e~y0ZbYIXMmRwyBURr`lXwg zp>YuB^lZZC+;0RnI*bHy%(?h@-Py%Y1nocyKo?*oo78O{R&;=eMXL;E&{Q0VVgXgV z0ugdbO{bQ1ggij+CJ-gOb?i~;*;WX{%+5g*2T4SRY|F77aKynq*x&dAkV|9}Af#(G z`LnM*2o8SM(OvBryVo(c-nHj`*ZAGYc+=ib-S19(BJYL!676xAZXNjbkzXEZuznWq zsD_8{g@+*+TlE17boN%GVqh5HE1RF-HnV{ z@!{3bx*V&@6BT*FibU4}*8^6h!-|bt{X^CMiAw(j;Dyx_dry8xwt5Dwfyb=z!~f_A zgxXkmm#oKO@KR1;cMgqojTFgkZkA#gl;GHD8pvFaKmCdV?o6i;fbI~kLjYRmxD3-+ zngJ20s&AVJA6obEn$FU2vmD_@&dciE_bz3}- zj?VUjze(x~5T6_Pa;W)69IapcKXJ6f@B^4^vbSm`wyIVhKf9pdlc(Pf@g7Qc-9OyHEgn010MP^e~bsBzV+L5{5UK;`L+%jo;W0 z1A76#F;Yh&TGsGbuh%It%uKfM#Q#<$2m?6)x5ko>a2y!B;nsEE_~KT zq3e-^&I>6WHz#O3ByA!jb&$*zMM!dd_4IN1z?73iy8%($Jg1uRq?(OWCy8Sz+JuhT z@hA4N8eSto-7W))0N%Mn+6Hez~ z6u55T&7jqT`BVtpF62!uE*5GW1+V=U$W~{zZdV|VY__W|0uoD8}C_RpZ z*)tklf_E;W*Wt6j!K6W3rArIOmQ_Kg@*a>-Pe``c)mA8U5Lk{eIr(#)8LoKjHz0kha>TDI4xGDmV z3qJ?#MCYWZU^)5?B+NaYz}68U+aZo&%T{A{;OwW!cn}B}Gel{VS0~YH&0d+U$|Dtd z&V~v0yIldm286JOX|61r&>m2jbjh%_E2d4`p7Qs09Skfmg;hn`px?Xp052K;a7-MFrY{dZLz2 zEiiz!JHe3ZFf{FapE(VX#F879olv~Ujy3zIFDCW8naX9^S25e0TflE@4gfRhwj;AG z9dbV3P109j5riuP-*bcKIPR}x4E!|rZSG5;WB(L*&huq}aD$s(j`OdkHVIUlQi0<} XZ@j!ou-?q`?cCtX;+F&}cBKCUXnB?) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/et_xmlfile/incremental_tree.py b/venv/Lib/site-packages/et_xmlfile/incremental_tree.py new file mode 100644 index 0000000..b735c1b --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile/incremental_tree.py @@ -0,0 +1,917 @@ +# Code modified from cPython's Lib/xml/etree/ElementTree.py +# The write() code is modified to allow specifying a particular namespace +# uri -> prefix mapping. +# +# --------------------------------------------------------------------- +# Licensed to PSF under a Contributor Agreement. +# See https://www.python.org/psf/license for licensing details. +# +# ElementTree +# Copyright (c) 1999-2008 by Fredrik Lundh. All rights reserved. +# +# fredrik@pythonware.com +# http://www.pythonware.com +# -------------------------------------------------------------------- +# The ElementTree toolkit is +# +# Copyright (c) 1999-2008 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- +import contextlib +import io + +import xml.etree.ElementTree as ET + + +def current_global_nsmap(): + return { + prefix: uri for uri, prefix in ET._namespace_map.items() + } + + +class IncrementalTree(ET.ElementTree): + + def write( + self, + file_or_filename, + encoding=None, + xml_declaration=None, + default_namespace=None, + method=None, + *, + short_empty_elements=True, + nsmap=None, + root_ns_only=False, + minimal_ns_only=False, + ): + """Write element tree to a file as XML. + + Arguments: + *file_or_filename* -- file name or a file object opened for writing + + *encoding* -- the output encoding (default: US-ASCII) + + *xml_declaration* -- bool indicating if an XML declaration should be + added to the output. If None, an XML declaration + is added if encoding IS NOT either of: + US-ASCII, UTF-8, or Unicode + + *default_namespace* -- sets the default XML namespace (for "xmlns"). + Takes precedence over any default namespace + provided in nsmap or + xml.etree.ElementTree.register_namespace(). + + *method* -- either "xml" (default), "html, "text", or "c14n" + + *short_empty_elements* -- controls the formatting of elements + that contain no content. If True (default) + they are emitted as a single self-closed + tag, otherwise they are emitted as a pair + of start/end tags + + *nsmap* -- a mapping of namespace prefixes to URIs. These take + precedence over any mappings registered using + xml.etree.ElementTree.register_namespace(). The + default_namespace argument, if supplied, takes precedence + over any default namespace supplied in nsmap. All supplied + namespaces will be declared on the root element, even if + unused in the document. + + *root_ns_only* -- bool indicating namespace declrations should only + be written on the root element. This requires two + passes of the xml tree adding additional time to + the writing process. This is primarily meant to + mimic xml.etree.ElementTree's behaviour. + + *minimal_ns_only* -- bool indicating only namespaces that were used + to qualify elements or attributes should be + declared. All namespace declarations will be + written on the root element regardless of the + value of the root_ns_only arg. Requires two + passes of the xml tree adding additional time to + the writing process. + + """ + if not method: + method = "xml" + elif method not in ("text", "xml", "html"): + raise ValueError("unknown method %r" % method) + if not encoding: + encoding = "us-ascii" + + with _get_writer(file_or_filename, encoding) as (write, declared_encoding): + if method == "xml" and ( + xml_declaration + or ( + xml_declaration is None + and encoding.lower() != "unicode" + and declared_encoding.lower() not in ("utf-8", "us-ascii") + ) + ): + write("\n" % (declared_encoding,)) + if method == "text": + ET._serialize_text(write, self._root) + else: + if method == "xml": + is_html = False + else: + is_html = True + if nsmap: + if None in nsmap: + raise ValueError( + 'Found None as default nsmap prefix in nsmap. ' + 'Use "" as the default namespace prefix.' + ) + new_nsmap = nsmap.copy() + else: + new_nsmap = {} + if default_namespace: + new_nsmap[""] = default_namespace + if root_ns_only or minimal_ns_only: + # _namespaces returns a mapping of only the namespaces that + # were used. + new_nsmap = _namespaces( + self._root, + default_namespace, + new_nsmap, + ) + if not minimal_ns_only: + if nsmap: + # We want all namespaces defined in the provided + # nsmap to be declared regardless of whether + # they've been used. + new_nsmap.update(nsmap) + if default_namespace: + new_nsmap[""] = default_namespace + global_nsmap = { + prefix: uri for uri, prefix in ET._namespace_map.items() + } + if None in global_nsmap: + raise ValueError( + 'Found None as default nsmap prefix in nsmap registered with ' + 'register_namespace. Use "" for the default namespace prefix.' + ) + nsmap_scope = {} + _serialize_ns_xml( + write, + self._root, + nsmap_scope, + global_nsmap, + is_html=is_html, + is_root=True, + short_empty_elements=short_empty_elements, + new_nsmap=new_nsmap, + ) + + +def _make_new_ns_prefix( + nsmap_scope, + global_prefixes, + local_nsmap=None, + default_namespace=None, +): + i = len(nsmap_scope) + if default_namespace is not None and "" not in nsmap_scope: + # Keep the same numbering scheme as python which assumes the default + # namespace is present if supplied. + i += 1 + + while True: + prefix = f"ns{i}" + if ( + prefix not in nsmap_scope + and prefix not in global_prefixes + and ( + not local_nsmap or prefix not in local_nsmap + ) + ): + return prefix + i += 1 + + +def _get_or_create_prefix( + uri, + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + for_default_namespace_attr_prefix=False, +): + """Find a prefix that doesn't conflict with the ns scope or create a new prefix + + This function mutates nsmap_scope, global_nsmap, new_namespace_prefixes and + uri_to_prefix. It is intended to keep state in _serialize_ns_xml consistent + while deduplicating the house keeping code or updating these dictionaries. + """ + # Check if we can reuse an existing (global) prefix within the current + # namespace scope. There maybe many prefixes pointing to a single URI by + # this point and we need to select a prefix that is not in use in the + # current scope. + for global_prefix, global_uri in global_nsmap.items(): + if uri == global_uri and global_prefix not in nsmap_scope: + prefix = global_prefix + break + else: # no break + # We couldn't find a suitable existing prefix for this namespace scope, + # let's create a new one. + prefix = _make_new_ns_prefix(nsmap_scope, global_prefixes=global_nsmap) + global_nsmap[prefix] = uri + nsmap_scope[prefix] = uri + if not for_default_namespace_attr_prefix: + # Don't override the actual default namespace prefix + uri_to_prefix[uri] = prefix + if prefix != "xml": + new_namespace_prefixes.add(prefix) + return prefix + + +def _find_default_namespace_attr_prefix( + default_namespace, + nsmap, + local_nsmap, + global_prefixes, + provided_default_namespace=None, +): + # Search the provided nsmap for any prefixes for this uri that aren't the + # default namespace "" + for prefix, uri in nsmap.items(): + if uri == default_namespace and prefix != "": + return prefix + + for prefix, uri in local_nsmap.items(): + if uri == default_namespace and prefix != "": + return prefix + + # _namespace_map is a 1:1 mapping of uri -> prefix + prefix = ET._namespace_map.get(default_namespace) + if prefix and prefix not in nsmap: + return prefix + + return _make_new_ns_prefix( + nsmap, + global_prefixes, + local_nsmap, + provided_default_namespace, + ) + + +def process_attribs( + elem, + is_nsmap_scope_changed, + default_ns_attr_prefix, + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, +): + item_parts = [] + for k, v in elem.items(): + if isinstance(k, ET.QName): + k = k.text + try: + if k[:1] == "{": + uri_and_name = k[1:].rsplit("}", 1) + try: + prefix = uri_to_prefix[uri_and_name[0]] + except KeyError: + if not is_nsmap_scope_changed: + # We're about to mutate the these dicts so + # let's copy them first. We don't have to + # recompute other mappings as we're looking up + # or creating a new prefix + nsmap_scope = nsmap_scope.copy() + uri_to_prefix = uri_to_prefix.copy() + is_nsmap_scope_changed = True + prefix = _get_or_create_prefix( + uri_and_name[0], + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + ) + + if not prefix: + if default_ns_attr_prefix: + prefix = default_ns_attr_prefix + else: + for prefix, known_uri in nsmap_scope.items(): + if known_uri == uri_and_name[0] and prefix != "": + default_ns_attr_prefix = prefix + break + else: # no break + if not is_nsmap_scope_changed: + # We're about to mutate the these dicts so + # let's copy them first. We don't have to + # recompute other mappings as we're looking up + # or creating a new prefix + nsmap_scope = nsmap_scope.copy() + uri_to_prefix = uri_to_prefix.copy() + is_nsmap_scope_changed = True + prefix = _get_or_create_prefix( + uri_and_name[0], + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + for_default_namespace_attr_prefix=True, + ) + default_ns_attr_prefix = prefix + k = f"{prefix}:{uri_and_name[1]}" + except TypeError: + ET._raise_serialization_error(k) + + if isinstance(v, ET.QName): + if v.text[:1] != "{": + v = v.text + else: + uri_and_name = v.text[1:].rsplit("}", 1) + try: + prefix = uri_to_prefix[uri_and_name[0]] + except KeyError: + if not is_nsmap_scope_changed: + # We're about to mutate the these dicts so + # let's copy them first. We don't have to + # recompute other mappings as we're looking up + # or creating a new prefix + nsmap_scope = nsmap_scope.copy() + uri_to_prefix = uri_to_prefix.copy() + is_nsmap_scope_changed = True + prefix = _get_or_create_prefix( + uri_and_name[0], + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + ) + v = f"{prefix}:{uri_and_name[1]}" + item_parts.append((k, v)) + return item_parts, default_ns_attr_prefix, nsmap_scope + + +def write_elem_start( + write, + elem, + nsmap_scope, + global_nsmap, + short_empty_elements, + is_html, + is_root=False, + uri_to_prefix=None, + default_ns_attr_prefix=None, + new_nsmap=None, + **kwargs, +): + """Write the opening tag (including self closing) and element text. + + Refer to _serialize_ns_xml for description of arguments. + + nsmap_scope should be an empty dictionary on first call. All nsmap prefixes + must be strings with the default namespace prefix represented by "". + + eg. + - (returns tag = 'foo') + - text (returns tag = 'foo') + - (returns tag = None) + + Returns: + tag: + The tag name to be closed or None if no closing required. + nsmap_scope: + The current nsmap after any prefix to uri additions from this + element. This is the input dict if unmodified or an updated copy. + default_ns_attr_prefix: + The prefix for the default namespace to use with attrs. + uri_to_prefix: + The current uri to prefix map after any uri to prefix additions + from this element. This is the input dict if unmodified or an + updated copy. + next_remains_root: + A bool indicating if the child element(s) should be treated as + their own roots. + """ + tag = elem.tag + text = elem.text + + if tag is ET.Comment: + write("" % text) + tag = None + next_remains_root = False + elif tag is ET.ProcessingInstruction: + write("" % text) + tag = None + next_remains_root = False + else: + if new_nsmap: + is_nsmap_scope_changed = True + nsmap_scope = nsmap_scope.copy() + nsmap_scope.update(new_nsmap) + new_namespace_prefixes = set(new_nsmap.keys()) + new_namespace_prefixes.discard("xml") + # We need to recompute the uri to prefixes + uri_to_prefix = None + default_ns_attr_prefix = None + else: + is_nsmap_scope_changed = False + new_namespace_prefixes = set() + + if uri_to_prefix is None: + if None in nsmap_scope: + raise ValueError( + 'Found None as a namespace prefix. Use "" as the default namespace prefix.' + ) + uri_to_prefix = {uri: prefix for prefix, uri in nsmap_scope.items()} + if "" in nsmap_scope: + # There may be multiple prefixes for the default namespace but + # we want to make sure we preferentially use "" (for elements) + uri_to_prefix[nsmap_scope[""]] = "" + + if tag is None: + # tag supression where tag is set to None + # Don't change is_root so namespaces can be passed down + next_remains_root = is_root + if text: + write(ET._escape_cdata(text)) + else: + next_remains_root = False + if isinstance(tag, ET.QName): + tag = tag.text + try: + # These splits / fully qualified tag creationg are the + # bottleneck in this implementation vs the python + # implementation. + # The following split takes ~42ns with no uri and ~85ns if a + # prefix is present. If the uri was present, we then need to + # look up a prefix (~14ns) and create the fully qualified + # string (~41ns). This gives a total of ~140ns where a uri is + # present. + # Python's implementation needs to preprocess the tree to + # create a dict of qname -> tag by traversing the tree which + # takes a bit of extra time but it quickly makes that back by + # only having to do a dictionary look up (~14ns) for each tag / + # attrname vs our splitting (~140ns). + # So here we have the flexibility of being able to redefine the + # uri a prefix points to midway through serialisation at the + # expense of performance (~10% slower for a 1mb file on my + # machine). + if tag[:1] == "{": + uri_and_name = tag[1:].rsplit("}", 1) + try: + prefix = uri_to_prefix[uri_and_name[0]] + except KeyError: + if not is_nsmap_scope_changed: + # We're about to mutate the these dicts so let's + # copy them first. We don't have to recompute other + # mappings as we're looking up or creating a new + # prefix + nsmap_scope = nsmap_scope.copy() + uri_to_prefix = uri_to_prefix.copy() + is_nsmap_scope_changed = True + prefix = _get_or_create_prefix( + uri_and_name[0], + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + ) + if prefix: + tag = f"{prefix}:{uri_and_name[1]}" + else: + tag = uri_and_name[1] + elif "" in nsmap_scope: + raise ValueError( + "cannot use non-qualified names with default_namespace option" + ) + except TypeError: + ET._raise_serialization_error(tag) + + write("<" + tag) + + if elem.attrib: + item_parts, default_ns_attr_prefix, nsmap_scope = process_attribs( + elem, + is_nsmap_scope_changed, + default_ns_attr_prefix, + nsmap_scope, + global_nsmap, + new_namespace_prefixes, + uri_to_prefix, + ) + else: + item_parts = [] + if new_namespace_prefixes: + ns_attrs = [] + for k in sorted(new_namespace_prefixes): + v = nsmap_scope[k] + if k: + k = "xmlns:" + k + else: + k = "xmlns" + ns_attrs.append((k, v)) + if is_html: + write("".join([f' {k}="{ET._escape_attrib_html(v)}"' for k, v in ns_attrs])) + else: + write("".join([f' {k}="{ET._escape_attrib(v)}"' for k, v in ns_attrs])) + if item_parts: + if is_html: + write("".join([f' {k}="{ET._escape_attrib_html(v)}"' for k, v in item_parts])) + else: + write("".join([f' {k}="{ET._escape_attrib(v)}"' for k, v in item_parts])) + if is_html: + write(">") + ltag = tag.lower() + if text: + if ltag == "script" or ltag == "style": + write(text) + else: + write(ET._escape_cdata(text)) + if ltag in ET.HTML_EMPTY: + tag = None + elif text or len(elem) or not short_empty_elements: + write(">") + if text: + write(ET._escape_cdata(text)) + else: + tag = None + write(" />") + return ( + tag, + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + next_remains_root, + ) + + +def _serialize_ns_xml( + write, + elem, + nsmap_scope, + global_nsmap, + short_empty_elements, + is_html, + is_root=False, + uri_to_prefix=None, + default_ns_attr_prefix=None, + new_nsmap=None, + **kwargs, +): + """Serialize an element or tree using 'write' for output. + + Args: + write: + A function to write the xml to its destination. + elem: + The element to serialize. + nsmap_scope: + The current prefix to uri mapping for this element. This should be + an empty dictionary for the root element. Additional namespaces are + progressively added using the new_nsmap arg. + global_nsmap: + A dict copy of the globally registered _namespace_map in uri to + prefix form + short_empty_elements: + Controls the formatting of elements that contain no content. If True + (default) they are emitted as a single self-closed tag, otherwise + they are emitted as a pair of start/end tags. + is_html: + Set to True to serialize as HTML otherwise XML. + is_root: + Boolean indicating if this is a root element. + uri_to_prefix: + Current state of the mapping of uri to prefix. + default_ns_attr_prefix: + new_nsmap: + New prefix -> uri mapping to be applied to this element. + """ + ( + tag, + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + next_remains_root, + ) = write_elem_start( + write, + elem, + nsmap_scope, + global_nsmap, + short_empty_elements, + is_html, + is_root, + uri_to_prefix, + default_ns_attr_prefix, + new_nsmap=new_nsmap, + ) + for e in elem: + _serialize_ns_xml( + write, + e, + nsmap_scope, + global_nsmap, + short_empty_elements, + is_html, + next_remains_root, + uri_to_prefix, + default_ns_attr_prefix, + new_nsmap=None, + ) + if tag: + write(f"") + if elem.tail: + write(ET._escape_cdata(elem.tail)) + + +def _qnames_iter(elem): + """Iterate through all the qualified names in elem""" + seen_el_qnames = set() + seen_other_qnames = set() + for this_elem in elem.iter(): + tag = this_elem.tag + if isinstance(tag, str): + if tag not in seen_el_qnames: + seen_el_qnames.add(tag) + yield tag, True + elif isinstance(tag, ET.QName): + tag = tag.text + if tag not in seen_el_qnames: + seen_el_qnames.add(tag) + yield tag, True + elif ( + tag is not None + and tag is not ET.ProcessingInstruction + and tag is not ET.Comment + ): + ET._raise_serialization_error(tag) + + for key, value in this_elem.items(): + if isinstance(key, ET.QName): + key = key.text + if key not in seen_other_qnames: + seen_other_qnames.add(key) + yield key, False + + if isinstance(value, ET.QName): + if value.text not in seen_other_qnames: + seen_other_qnames.add(value.text) + yield value.text, False + + text = this_elem.text + if isinstance(text, ET.QName): + if text.text not in seen_other_qnames: + seen_other_qnames.add(text.text) + yield text.text, False + + +def _namespaces( + elem, + default_namespace=None, + nsmap=None, +): + """Find all namespaces used in the document and return a prefix to uri map""" + if nsmap is None: + nsmap = {} + + out_nsmap = {} + + seen_uri_to_prefix = {} + # Multiple prefixes may be present for a single uri. This will select the + # last prefix found in nsmap for a given uri. + local_prefix_map = {uri: prefix for prefix, uri in nsmap.items()} + if default_namespace is not None: + local_prefix_map[default_namespace] = "" + elif "" in nsmap: + # but we make sure the default prefix always take precedence + local_prefix_map[nsmap[""]] = "" + + global_prefixes = set(ET._namespace_map.values()) + has_unqual_el = False + default_namespace_attr_prefix = None + for qname, is_el in _qnames_iter(elem): + try: + if qname[:1] == "{": + uri_and_name = qname[1:].rsplit("}", 1) + + prefix = seen_uri_to_prefix.get(uri_and_name[0]) + if prefix is None: + prefix = local_prefix_map.get(uri_and_name[0]) + if prefix is None or prefix in out_nsmap: + prefix = ET._namespace_map.get(uri_and_name[0]) + if prefix is None or prefix in out_nsmap: + prefix = _make_new_ns_prefix( + out_nsmap, + global_prefixes, + nsmap, + default_namespace, + ) + if prefix or is_el: + out_nsmap[prefix] = uri_and_name[0] + seen_uri_to_prefix[uri_and_name[0]] = prefix + + if not is_el and not prefix and not default_namespace_attr_prefix: + # Find the alternative prefix to use with non-element + # names + default_namespace_attr_prefix = _find_default_namespace_attr_prefix( + uri_and_name[0], + out_nsmap, + nsmap, + global_prefixes, + default_namespace, + ) + out_nsmap[default_namespace_attr_prefix] = uri_and_name[0] + # Don't add this uri to prefix mapping as it might override + # the uri -> "" default mapping. We'll fix this up at the + # end of the fn. + # local_prefix_map[uri_and_name[0]] = default_namespace_attr_prefix + else: + if is_el: + has_unqual_el = True + except TypeError: + ET._raise_serialization_error(qname) + + if "" in out_nsmap and has_unqual_el: + # FIXME: can this be handled in XML 1.0? + raise ValueError( + "cannot use non-qualified names with default_namespace option" + ) + + # The xml prefix doesn't need to be declared but may have been used to + # prefix names. Let's remove it if it has been used + out_nsmap.pop("xml", None) + return out_nsmap + + +def tostring( + element, + encoding=None, + method=None, + *, + xml_declaration=None, + default_namespace=None, + short_empty_elements=True, + nsmap=None, + root_ns_only=False, + minimal_ns_only=False, + tree_cls=IncrementalTree, +): + """Generate string representation of XML element. + + All subelements are included. If encoding is "unicode", a string + is returned. Otherwise a bytestring is returned. + + *element* is an Element instance, *encoding* is an optional output + encoding defaulting to US-ASCII, *method* is an optional output which can + be one of "xml" (default), "html", "text" or "c14n", *default_namespace* + sets the default XML namespace (for "xmlns"). + + Returns an (optionally) encoded string containing the XML data. + + """ + stream = io.StringIO() if encoding == "unicode" else io.BytesIO() + tree_cls(element).write( + stream, + encoding, + xml_declaration=xml_declaration, + default_namespace=default_namespace, + method=method, + short_empty_elements=short_empty_elements, + nsmap=nsmap, + root_ns_only=root_ns_only, + minimal_ns_only=minimal_ns_only, + ) + return stream.getvalue() + + +def tostringlist( + element, + encoding=None, + method=None, + *, + xml_declaration=None, + default_namespace=None, + short_empty_elements=True, + nsmap=None, + root_ns_only=False, + minimal_ns_only=False, + tree_cls=IncrementalTree, +): + lst = [] + stream = ET._ListDataStream(lst) + tree_cls(element).write( + stream, + encoding, + xml_declaration=xml_declaration, + default_namespace=default_namespace, + method=method, + short_empty_elements=short_empty_elements, + nsmap=nsmap, + root_ns_only=root_ns_only, + minimal_ns_only=minimal_ns_only, + ) + return lst + + +def compat_tostring( + element, + encoding=None, + method=None, + *, + xml_declaration=None, + default_namespace=None, + short_empty_elements=True, + nsmap=None, + root_ns_only=True, + minimal_ns_only=False, + tree_cls=IncrementalTree, +): + """tostring with options that produce the same results as xml.etree.ElementTree.tostring + + root_ns_only=True is a bit slower than False as it needs to traverse the + tree one more time to collect all the namespaces. + """ + return tostring( + element, + encoding=encoding, + method=method, + xml_declaration=xml_declaration, + default_namespace=default_namespace, + short_empty_elements=short_empty_elements, + nsmap=nsmap, + root_ns_only=root_ns_only, + minimal_ns_only=minimal_ns_only, + tree_cls=tree_cls, + ) + + +# -------------------------------------------------------------------- +# serialization support + +@contextlib.contextmanager +def _get_writer(file_or_filename, encoding): + # Copied from Python 3.12 + # returns text write method and release all resources after using + try: + write = file_or_filename.write + except AttributeError: + # file_or_filename is a file name + if encoding.lower() == "unicode": + encoding = "utf-8" + with open(file_or_filename, "w", encoding=encoding, + errors="xmlcharrefreplace") as file: + yield file.write, encoding + else: + # file_or_filename is a file-like object + # encoding determines if it is a text or binary writer + if encoding.lower() == "unicode": + # use a text writer as is + yield write, getattr(file_or_filename, "encoding", None) or "utf-8" + else: + # wrap a binary writer with TextIOWrapper + with contextlib.ExitStack() as stack: + if isinstance(file_or_filename, io.BufferedIOBase): + file = file_or_filename + elif isinstance(file_or_filename, io.RawIOBase): + file = io.BufferedWriter(file_or_filename) + # Keep the original file open when the BufferedWriter is + # destroyed + stack.callback(file.detach) + else: + # This is to handle passed objects that aren't in the + # IOBase hierarchy, but just have a write method + file = io.BufferedIOBase() + file.writable = lambda: True + file.write = write + try: + # TextIOWrapper uses this methods to determine + # if BOM (for UTF-16, etc) should be added + file.seekable = file_or_filename.seekable + file.tell = file_or_filename.tell + except AttributeError: + pass + file = io.TextIOWrapper(file, + encoding=encoding, + errors="xmlcharrefreplace", + newline="\n") + # Keep the original file open when the TextIOWrapper is + # destroyed + stack.callback(file.detach) + yield file.write, encoding diff --git a/venv/Lib/site-packages/et_xmlfile/xmlfile.py b/venv/Lib/site-packages/et_xmlfile/xmlfile.py new file mode 100644 index 0000000..9b8ce82 --- /dev/null +++ b/venv/Lib/site-packages/et_xmlfile/xmlfile.py @@ -0,0 +1,158 @@ +from __future__ import absolute_import +# Copyright (c) 2010-2015 openpyxl + +"""Implements the lxml.etree.xmlfile API using the standard library xml.etree""" + + +from contextlib import contextmanager + +from xml.etree.ElementTree import ( + Element, + _escape_cdata, +) + +from . import incremental_tree + + +class LxmlSyntaxError(Exception): + pass + + +class _IncrementalFileWriter(object): + """Replacement for _IncrementalFileWriter of lxml""" + def __init__(self, output_file): + self._element_stack = [] + self._file = output_file + self._have_root = False + self.global_nsmap = incremental_tree.current_global_nsmap() + self.is_html = False + + @contextmanager + def element(self, tag, attrib=None, nsmap=None, **_extra): + """Create a new xml element using a context manager.""" + if nsmap and None in nsmap: + # Normalise None prefix (lxml's default namespace prefix) -> "", as + # required for incremental_tree + if "" in nsmap and nsmap[""] != nsmap[None]: + raise ValueError( + 'Found None and "" as default nsmap prefixes with different URIs' + ) + nsmap = nsmap.copy() + nsmap[""] = nsmap.pop(None) + + # __enter__ part + self._have_root = True + if attrib is None: + attrib = {} + elem = Element(tag, attrib=attrib, **_extra) + elem.text = '' + elem.tail = '' + if self._element_stack: + is_root = False + ( + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + ) = self._element_stack[-1] + else: + is_root = True + nsmap_scope = {} + default_ns_attr_prefix = None + uri_to_prefix = {} + ( + tag, + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + next_remains_root, + ) = incremental_tree.write_elem_start( + self._file, + elem, + nsmap_scope=nsmap_scope, + global_nsmap=self.global_nsmap, + short_empty_elements=False, + is_html=self.is_html, + is_root=is_root, + uri_to_prefix=uri_to_prefix, + default_ns_attr_prefix=default_ns_attr_prefix, + new_nsmap=nsmap, + ) + self._element_stack.append( + ( + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + ) + ) + yield + + # __exit__ part + self._element_stack.pop() + self._file(f"") + if elem.tail: + self._file(_escape_cdata(elem.tail)) + + def write(self, arg): + """Write a string or subelement.""" + + if isinstance(arg, str): + # it is not allowed to write a string outside of an element + if not self._element_stack: + raise LxmlSyntaxError() + self._file(_escape_cdata(arg)) + + else: + if not self._element_stack and self._have_root: + raise LxmlSyntaxError() + + if self._element_stack: + is_root = False + ( + nsmap_scope, + default_ns_attr_prefix, + uri_to_prefix, + ) = self._element_stack[-1] + else: + is_root = True + nsmap_scope = {} + default_ns_attr_prefix = None + uri_to_prefix = {} + incremental_tree._serialize_ns_xml( + self._file, + arg, + nsmap_scope=nsmap_scope, + global_nsmap=self.global_nsmap, + short_empty_elements=True, + is_html=self.is_html, + is_root=is_root, + uri_to_prefix=uri_to_prefix, + default_ns_attr_prefix=default_ns_attr_prefix, + ) + + def __enter__(self): + pass + + def __exit__(self, type, value, traceback): + # without root the xml document is incomplete + if not self._have_root: + raise LxmlSyntaxError() + + +class xmlfile(object): + """Context manager that can replace lxml.etree.xmlfile.""" + def __init__(self, output_file, buffered=False, encoding="utf-8", close=False): + self._file = output_file + self._close = close + self.encoding = encoding + self.writer_cm = None + + def __enter__(self): + self.writer_cm = incremental_tree._get_writer(self._file, encoding=self.encoding) + writer, declared_encoding = self.writer_cm.__enter__() + return _IncrementalFileWriter(writer) + + def __exit__(self, type, value, traceback): + if self.writer_cm: + self.writer_cm.__exit__(type, value, traceback) + if self._close: + self._file.close() diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/INSTALLER b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/LICENCE.rst b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/LICENCE.rst new file mode 100644 index 0000000..82213c5 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/LICENCE.rst @@ -0,0 +1,23 @@ +This software is under the MIT Licence +====================================== + +Copyright (c) 2010 openpyxl + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/METADATA b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/METADATA new file mode 100644 index 0000000..bac5c46 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/METADATA @@ -0,0 +1,86 @@ +Metadata-Version: 2.1 +Name: openpyxl +Version: 3.1.5 +Summary: A Python library to read/write Excel 2010 xlsx/xlsm files +Home-page: https://openpyxl.readthedocs.io +Author: See AUTHORS +Author-email: charlie.clark@clark-consulting.eu +License: MIT +Project-URL: Documentation, https://openpyxl.readthedocs.io/en/stable/ +Project-URL: Source, https://foss.heptapod.net/openpyxl/openpyxl +Project-URL: Tracker, https://foss.heptapod.net/openpyxl/openpyxl/-/issues +Classifier: Development Status :: 5 - Production/Stable +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Requires-Python: >=3.8 +License-File: LICENCE.rst +Requires-Dist: et-xmlfile + +.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default + :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default + :alt: coverage status + +Introduction +------------ + +openpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files. + +It was born from lack of existing library to read/write natively from Python +the Office Open XML format. + +All kudos to the PHPExcel team as openpyxl was initially based on PHPExcel. + + +Security +-------- + +By default openpyxl does not guard against quadratic blowup or billion laughs +xml attacks. To guard against these attacks install defusedxml. + +Mailing List +------------ + +The user list can be found on http://groups.google.com/group/openpyxl-users + + +Sample code:: + + from openpyxl import Workbook + wb = Workbook() + + # grab the active worksheet + ws = wb.active + + # Data can be assigned directly to cells + ws['A1'] = 42 + + # Rows can also be appended + ws.append([1, 2, 3]) + + # Python types will automatically be converted + import datetime + ws['A2'] = datetime.datetime.now() + + # Save the file + wb.save("sample.xlsx") + + +Documentation +------------- + +The documentation is at: https://openpyxl.readthedocs.io + +* installation methods +* code examples +* instructions for contributing + +Release notes: https://openpyxl.readthedocs.io/en/stable/changes.html diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/RECORD b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/RECORD new file mode 100644 index 0000000..ee84af8 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/RECORD @@ -0,0 +1,387 @@ +openpyxl-3.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +openpyxl-3.1.5.dist-info/LICENCE.rst,sha256=DIS7QvXTZ-Xr-fwt3jWxYUHfXuD9wYklCFi8bFVg9p4,1131 +openpyxl-3.1.5.dist-info/METADATA,sha256=I_gMqYMN2JQ12hcQ8m3tqPgeVAkofnRUAhDHJiekrZY,2510 +openpyxl-3.1.5.dist-info/RECORD,, +openpyxl-3.1.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +openpyxl-3.1.5.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110 +openpyxl-3.1.5.dist-info/top_level.txt,sha256=mKJO5QFAsUEDtJ_c97F-IbmVtHYEDymqD7d5X0ULkVs,9 +openpyxl/__init__.py,sha256=s2sXcp8ThXXHswNSh-UuQi5BHsoasuczUyjNNz0Vupc,603 +openpyxl/__pycache__/__init__.cpython-312.pyc,, +openpyxl/__pycache__/_constants.cpython-312.pyc,, +openpyxl/_constants.py,sha256=rhOeQ6wNH6jw73G4I242VtbmyM8fvdNVwOsOjJlJ6TU,306 +openpyxl/cell/__init__.py,sha256=OXNzFFR9dlxUXiuWXyKSVQRJiQhZFel-_RQS3mHNnrQ,122 +openpyxl/cell/__pycache__/__init__.cpython-312.pyc,, +openpyxl/cell/__pycache__/_writer.cpython-312.pyc,, +openpyxl/cell/__pycache__/cell.cpython-312.pyc,, +openpyxl/cell/__pycache__/read_only.cpython-312.pyc,, +openpyxl/cell/__pycache__/rich_text.cpython-312.pyc,, +openpyxl/cell/__pycache__/text.cpython-312.pyc,, +openpyxl/cell/_writer.py,sha256=3I6WLKEJGuFe8rOjxdAVuDT4sZYjcYo57-6velGepdQ,4015 +openpyxl/cell/cell.py,sha256=hVJsMC9kJAxxb_CspJlBrwDt2qzfccO6YDfPHK3BBCQ,8922 +openpyxl/cell/read_only.py,sha256=ApXkofmUK5QISsuTgZvmZKsU8PufSQtqe2xmYWTgLnc,3097 +openpyxl/cell/rich_text.py,sha256=uAZmGB7bYDUnanHI0vJmKbfSF8riuIYS5CwlVU_3_fM,5628 +openpyxl/cell/text.py,sha256=acU6BZQNSmVx4bBXPgFavoxmfoPbVYrm_ztp1bGeOmc,4367 +openpyxl/chart/_3d.py,sha256=Sdm0TNpXHXNoOLUwiOSccv7yFwrel_-rjQhkrDqAAF4,3104 +openpyxl/chart/__init__.py,sha256=ag4YCN1B3JH0lkS7tiiZCohVAA51x_pejGdAMuxaI1Y,564 +openpyxl/chart/__pycache__/_3d.cpython-312.pyc,, +openpyxl/chart/__pycache__/__init__.cpython-312.pyc,, +openpyxl/chart/__pycache__/_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/area_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/axis.cpython-312.pyc,, +openpyxl/chart/__pycache__/bar_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/bubble_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/chartspace.cpython-312.pyc,, +openpyxl/chart/__pycache__/data_source.cpython-312.pyc,, +openpyxl/chart/__pycache__/descriptors.cpython-312.pyc,, +openpyxl/chart/__pycache__/error_bar.cpython-312.pyc,, +openpyxl/chart/__pycache__/label.cpython-312.pyc,, +openpyxl/chart/__pycache__/layout.cpython-312.pyc,, +openpyxl/chart/__pycache__/legend.cpython-312.pyc,, +openpyxl/chart/__pycache__/line_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/marker.cpython-312.pyc,, +openpyxl/chart/__pycache__/picture.cpython-312.pyc,, +openpyxl/chart/__pycache__/pie_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/pivot.cpython-312.pyc,, +openpyxl/chart/__pycache__/plotarea.cpython-312.pyc,, +openpyxl/chart/__pycache__/print_settings.cpython-312.pyc,, +openpyxl/chart/__pycache__/radar_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/reader.cpython-312.pyc,, +openpyxl/chart/__pycache__/reference.cpython-312.pyc,, +openpyxl/chart/__pycache__/scatter_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/series.cpython-312.pyc,, +openpyxl/chart/__pycache__/series_factory.cpython-312.pyc,, +openpyxl/chart/__pycache__/shapes.cpython-312.pyc,, +openpyxl/chart/__pycache__/stock_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/surface_chart.cpython-312.pyc,, +openpyxl/chart/__pycache__/text.cpython-312.pyc,, +openpyxl/chart/__pycache__/title.cpython-312.pyc,, +openpyxl/chart/__pycache__/trendline.cpython-312.pyc,, +openpyxl/chart/__pycache__/updown_bars.cpython-312.pyc,, +openpyxl/chart/_chart.py,sha256=j5xn6mQYmZ4E7y2V1Xvx1jwhX2_O68Mp-8zeXRteS7E,5746 +openpyxl/chart/area_chart.py,sha256=uROD3fdus6yD1TGu87j4z7KtOEH7tI-3Z5NFK73wwgw,2890 +openpyxl/chart/axis.py,sha256=yommy5q2mQWKmmLRouWBpimiBZDBM1K-UKAIwCwKDNc,12580 +openpyxl/chart/bar_chart.py,sha256=_TQHleMT3gSa6B1BkKD_FkLFcv8LRaoiHbpy2yflLO4,4142 +openpyxl/chart/bubble_chart.py,sha256=KL7VZYFyLDpA8MC-IFtRAUIN262xK6MzjU41DrSVgpY,2004 +openpyxl/chart/chartspace.py,sha256=PuPGBsVbpK5JagbB7SWgp4JwdQtTrZzIm8mf3kfGAuY,6069 +openpyxl/chart/data_source.py,sha256=GAuWoCOJ4k7RZNJZkZck0zt_-D5UfDEwqwQ3ND4-s34,5782 +openpyxl/chart/descriptors.py,sha256=uj-qptwKOBeg7U5xBN4QJQ2OwQvFQ7o4n5eMXXIWS7M,736 +openpyxl/chart/error_bar.py,sha256=GS_L7PiyKNnJVHvQqG2hLxEW237igLLCatCNC-xGMxk,1832 +openpyxl/chart/label.py,sha256=IjvI-CZjTY8ydoUzUOihcbxoRWiSpFb_ipD6C2I8Pu4,4133 +openpyxl/chart/layout.py,sha256=QHakp_CIcoNuvjyZMsQ2p_qP44DIQs4aquy7yln94JM,2040 +openpyxl/chart/legend.py,sha256=iPMycOhYDAVYd05OU_QDB-GSavdw_1L9CMuJIETOoGI,2040 +openpyxl/chart/line_chart.py,sha256=6tAyDCzFiuiBFuUDTWhQepH8xVCx2s57lH951cEcwn0,3951 +openpyxl/chart/marker.py,sha256=kfybMkshK3qefOUW7OX-Os0vfl5OCXfg8MytwHC2i-w,2600 +openpyxl/chart/picture.py,sha256=Q4eBNQMKQDHR91RnPc7tM-YZVdcnWncedUlfagj67gk,1156 +openpyxl/chart/pie_chart.py,sha256=UOvkjrBpNd_rT-rvKcpPeVd9dK-ELdMIaHjAUEr6oN8,4793 +openpyxl/chart/pivot.py,sha256=9kVDmnxnR0uQRQ-Wbl6qw8eew9LGhqomaDBaXqQGZY4,1741 +openpyxl/chart/plotarea.py,sha256=em7yorXFz9SmJruqOR4Pn-2oEj0Su4rnzyNc5e0IZ_U,5805 +openpyxl/chart/print_settings.py,sha256=UwB6Kn6xkLRBejXScl-utF8dkNhV7Lm3Lfk7ACpbRgs,1454 +openpyxl/chart/radar_chart.py,sha256=93I1Y1dmXZ6Y0F1VKXz9I3x1ufgwygBOdbPZumR5n3s,1521 +openpyxl/chart/reader.py,sha256=oQD-29oxSLW2yzXdyXNhzQYNXgM64Y3kVSOIkrPZCuU,802 +openpyxl/chart/reference.py,sha256=N3T4qYMH9BVrtbDRiKIZz-qGvPAdfquWTGL0XKxD9G8,3098 +openpyxl/chart/scatter_chart.py,sha256=JMU32jjxTj7txPJ2TebBHPS5UcMsRHVqLz_psnN2YZs,1563 +openpyxl/chart/series.py,sha256=k8eR8cviH9EPllRjjr_2a-lH5S3_HWBTLyE7XKghzWc,5896 +openpyxl/chart/series_factory.py,sha256=ey1zgNwM1g4bQwB9lLhM6E-ctLIM2kLWM3X7CPw8SDs,1368 +openpyxl/chart/shapes.py,sha256=JkgMy3DUWDKLV6JZHKb_pUBvWpzTAQ3biUMr-1fJWZU,2815 +openpyxl/chart/stock_chart.py,sha256=YJ7eElBX5omHziKo41ygTA7F_NEkyIlFUfdDJXZuKhM,1604 +openpyxl/chart/surface_chart.py,sha256=_-yGEX-Ou2NJVmJCA_K_bSLyzk-RvbPupyQLmjfCWj0,2914 +openpyxl/chart/text.py,sha256=voJCf4PK5olmX0g_5u9aQo8B5LpCUlOeq4j4pnOy_A0,1847 +openpyxl/chart/title.py,sha256=L-7KxwcpMb2aZk4ikgMsIgFPVtBafIppx9ykd5FPJ4w,1952 +openpyxl/chart/trendline.py,sha256=9pWSJa9Adwtd6v_i7dPT7qNKzhOrSMWZ4QuAOntZWVg,3045 +openpyxl/chart/updown_bars.py,sha256=QA4lyEMtMVvZCrYUpHZYMVS1xsnaN4_T5UBi6E7ilQ0,897 +openpyxl/chartsheet/__init__.py,sha256=3Ony1WNbxxWuddTW-peuUPvO3xqIWFWe3Da2OUzsVnI,71 +openpyxl/chartsheet/__pycache__/__init__.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/chartsheet.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/custom.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/properties.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/protection.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/publish.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/relation.cpython-312.pyc,, +openpyxl/chartsheet/__pycache__/views.cpython-312.pyc,, +openpyxl/chartsheet/chartsheet.py,sha256=GTXNfQPYBaS4B7XB4f7gDkAo2kCjtZqidl6iDxp-JQ8,3911 +openpyxl/chartsheet/custom.py,sha256=qVgeCzT7t1tN_pDwaLqtR3ubuPDLeTR5KKlcxwnTWa8,1691 +openpyxl/chartsheet/properties.py,sha256=dR1nrp22FsPkyDrwQaZV7t-p-Z2Jc88Y2IhIGbBvFhk,679 +openpyxl/chartsheet/protection.py,sha256=eJixEBmdoTDO2_0h6g51sdSdfSdCaP8UUNsbEqHds6U,1265 +openpyxl/chartsheet/publish.py,sha256=PrwqsUKn2SK67ZM3NEGT9FH4nOKC1cOxxm3322hHawQ,1587 +openpyxl/chartsheet/relation.py,sha256=ZAAfEZb639ve0k6ByRwmHdjBrjqVC0bHOLgIcBwRx6o,2731 +openpyxl/chartsheet/views.py,sha256=My3Au-DEAcC4lwBARhrCcwsN7Lp9H6cFQT-SiAcJlko,1341 +openpyxl/comments/__init__.py,sha256=k_QJ-OPRme8HgAYQlyxbbRhmS1n2FyowqIeekBW-7vw,67 +openpyxl/comments/__pycache__/__init__.cpython-312.pyc,, +openpyxl/comments/__pycache__/author.cpython-312.pyc,, +openpyxl/comments/__pycache__/comment_sheet.cpython-312.pyc,, +openpyxl/comments/__pycache__/comments.cpython-312.pyc,, +openpyxl/comments/__pycache__/shape_writer.cpython-312.pyc,, +openpyxl/comments/author.py,sha256=PZB_fjQqiEm8BdHDblbfzB0gzkFvECWq5i1jSHeJZco,388 +openpyxl/comments/comment_sheet.py,sha256=Uv2RPpIxrikDPHBr5Yj1dDkusZB97yVE-NQTM0-EnBk,5753 +openpyxl/comments/comments.py,sha256=CxurAWM7WbCdbeya-DQklbiWSFaxhtrUNBZEzulTyxc,1466 +openpyxl/comments/shape_writer.py,sha256=Ls1d0SscfxGM9H2spjxMNHeJSaZJuLawlXs4t4qH7v4,3809 +openpyxl/compat/__init__.py,sha256=fltF__CdGK97l2V3MtIDxbwgV_p1AZvLdyqcEtXKsqs,1592 +openpyxl/compat/__pycache__/__init__.cpython-312.pyc,, +openpyxl/compat/__pycache__/abc.cpython-312.pyc,, +openpyxl/compat/__pycache__/numbers.cpython-312.pyc,, +openpyxl/compat/__pycache__/product.cpython-312.pyc,, +openpyxl/compat/__pycache__/singleton.cpython-312.pyc,, +openpyxl/compat/__pycache__/strings.cpython-312.pyc,, +openpyxl/compat/abc.py,sha256=Y-L6pozzgjr81OfXsjDkGDeKEq6BOfMr6nvrFps_o6Q,155 +openpyxl/compat/numbers.py,sha256=2dckE0PHT7eB89Sc2BdlWOH4ZLXWt3_eo73-CzRujUY,1617 +openpyxl/compat/product.py,sha256=-bDgNMHGDgbahgw0jqale8TeIARLw7HO0soQAL9b_4k,264 +openpyxl/compat/singleton.py,sha256=R1HiH7XpjaW4kr3GILWMc4hRGZkXyc0yK7T1jcg_QWg,1023 +openpyxl/compat/strings.py,sha256=D_TWf8QnMH6WMx6xuCDfXl0boc1k9q7j8hGalVQ2RUk,604 +openpyxl/descriptors/__init__.py,sha256=eISTR0Sa1ZKKNQPxMZtqlE39JugYzkjxiZf7u9fttiw,1952 +openpyxl/descriptors/__pycache__/__init__.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/base.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/container.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/excel.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/namespace.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/nested.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/sequence.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/serialisable.cpython-312.pyc,, +openpyxl/descriptors/__pycache__/slots.cpython-312.pyc,, +openpyxl/descriptors/base.py,sha256=-CuNfswEGazgOoX3GuM2Bs2zkBImT992TvR2R1xsnXM,7135 +openpyxl/descriptors/container.py,sha256=IcO91M02hR0vXZtWGurz0IH1Vi2PoEECP1PEbz62FJQ,889 +openpyxl/descriptors/excel.py,sha256=d6a6mtoZ-33jwMGlgvNTL54cqLANKyhMihG6887j8r0,2412 +openpyxl/descriptors/namespace.py,sha256=LjI4e9R09NSbClr_ewv0YmHgWY8RO5xq1s-SpAvz2wo,313 +openpyxl/descriptors/nested.py,sha256=5LSsf2uvTKsrGEEQF1KVXMLHZFoRgmLfL_lzW0lWQjI,2603 +openpyxl/descriptors/sequence.py,sha256=OqF34K_nUC46XD5B_6xzGHeEICz_82hkFkNFXpBkSSE,3490 +openpyxl/descriptors/serialisable.py,sha256=U_7wMEGQRIOiimUUL4AbdOiWMc_aLyKeaRnj_Z7dVO8,7361 +openpyxl/descriptors/slots.py,sha256=xNj5vLWWoounpYqbP2JDnnhlTiTLRn-uTfQxncpFfn0,824 +openpyxl/drawing/__init__.py,sha256=xlXVaT3Fs9ltvbbRIGTSRow9kw9nhLY3Zj1Mm6vXRHE,66 +openpyxl/drawing/__pycache__/__init__.cpython-312.pyc,, +openpyxl/drawing/__pycache__/colors.cpython-312.pyc,, +openpyxl/drawing/__pycache__/connector.cpython-312.pyc,, +openpyxl/drawing/__pycache__/drawing.cpython-312.pyc,, +openpyxl/drawing/__pycache__/effect.cpython-312.pyc,, +openpyxl/drawing/__pycache__/fill.cpython-312.pyc,, +openpyxl/drawing/__pycache__/geometry.cpython-312.pyc,, +openpyxl/drawing/__pycache__/graphic.cpython-312.pyc,, +openpyxl/drawing/__pycache__/image.cpython-312.pyc,, +openpyxl/drawing/__pycache__/line.cpython-312.pyc,, +openpyxl/drawing/__pycache__/picture.cpython-312.pyc,, +openpyxl/drawing/__pycache__/properties.cpython-312.pyc,, +openpyxl/drawing/__pycache__/relation.cpython-312.pyc,, +openpyxl/drawing/__pycache__/spreadsheet_drawing.cpython-312.pyc,, +openpyxl/drawing/__pycache__/text.cpython-312.pyc,, +openpyxl/drawing/__pycache__/xdr.cpython-312.pyc,, +openpyxl/drawing/colors.py,sha256=d92d6LQv2xi4xVt0F6bEJz-kpe4ahghNsOIY0_cxgQI,15251 +openpyxl/drawing/connector.py,sha256=4be6kFwDmixqYX6ko22JE3cqJ9xUM7lRonSer1BDVgY,3863 +openpyxl/drawing/drawing.py,sha256=Wbv24TZbNaPngDR3adOj6jUBg-iyMYyfvgEPg-5IPu8,2339 +openpyxl/drawing/effect.py,sha256=vZ5r9k3JfyaAoBggFzN9wyvsEDnMnAmkQZsdVQN1-wo,9435 +openpyxl/drawing/fill.py,sha256=Z_kAY5bncgu1WkZNvgjiX5ucrYI6GLXyUi6H3_mne2k,13092 +openpyxl/drawing/geometry.py,sha256=0UM5hMHYy_R3C-lHt5x3NECDn7O1tfbKu5BweLwdLlg,17523 +openpyxl/drawing/graphic.py,sha256=013KhmTqp1PFKht9lRRA6SHjznxq9EL4u_ybA88OuCk,4811 +openpyxl/drawing/image.py,sha256=ROO0YJjzH9eqjPUKU5bMtt4bXnHFK9uofDa2__R3G2k,1455 +openpyxl/drawing/line.py,sha256=CRxV0NUpce4RfXPDllodcneoHk8vr2Ind8HaWnUv2HE,3904 +openpyxl/drawing/picture.py,sha256=tDYob2x4encQ9rUWOe29PqtiRSDEj746j-SvQ7rVV10,4205 +openpyxl/drawing/properties.py,sha256=TyLOF3ehp38XJvuupNZdsOqZ0HNXkVPBDYwU5O1GhBM,4948 +openpyxl/drawing/relation.py,sha256=InbM75ymWUjICXhjyCcYqp1FWcfCFp9q9vecYLptzk4,344 +openpyxl/drawing/spreadsheet_drawing.py,sha256=CUWSpIYWOHUEp-USOAGVNlLfXBQObcGdg_RZ_bggPYM,10721 +openpyxl/drawing/text.py,sha256=6_ShIu9FLG7MJvMLs_G_tTatTaBqxpaX5KMKxSfTY7Y,22421 +openpyxl/drawing/xdr.py,sha256=XE2yRzlCqoJBWg3TPRxelzZ4GmBV9dDFTtiJgJZku-U,626 +openpyxl/formatting/__init__.py,sha256=vpkL3EimMa-moJjcWk4l3bIWdJ3c7a8pKOfGlnPte9c,59 +openpyxl/formatting/__pycache__/__init__.cpython-312.pyc,, +openpyxl/formatting/__pycache__/formatting.cpython-312.pyc,, +openpyxl/formatting/__pycache__/rule.cpython-312.pyc,, +openpyxl/formatting/formatting.py,sha256=AdXlrhic4CPvyJ300oFJPJUH-2vS0VNOLiNudt3U26c,2701 +openpyxl/formatting/rule.py,sha256=96Fc5-hSByCrvkC1O0agEoZyL9G_AdeulrjRXnf_rZ8,9288 +openpyxl/formula/__init__.py,sha256=AgvEdunVryhzwecuFVO2EezdJT3h5gCXpw2j3f5VUWA,69 +openpyxl/formula/__pycache__/__init__.cpython-312.pyc,, +openpyxl/formula/__pycache__/tokenizer.cpython-312.pyc,, +openpyxl/formula/__pycache__/translate.cpython-312.pyc,, +openpyxl/formula/tokenizer.py,sha256=o1jDAOl79YiCWr-2LmSICyAbhm2hdb-37jriasmv4dc,15088 +openpyxl/formula/translate.py,sha256=Zs9adqfZTAuo8J_QNbqK3vjQDlSFhWc0vWc6TCMDYrI,6653 +openpyxl/packaging/__init__.py,sha256=KcNtO2zoYizOgG-iZzayZffSL1WeZR98i1Q8QYTRhfI,90 +openpyxl/packaging/__pycache__/__init__.cpython-312.pyc,, +openpyxl/packaging/__pycache__/core.cpython-312.pyc,, +openpyxl/packaging/__pycache__/custom.cpython-312.pyc,, +openpyxl/packaging/__pycache__/extended.cpython-312.pyc,, +openpyxl/packaging/__pycache__/interface.cpython-312.pyc,, +openpyxl/packaging/__pycache__/manifest.cpython-312.pyc,, +openpyxl/packaging/__pycache__/relationship.cpython-312.pyc,, +openpyxl/packaging/__pycache__/workbook.cpython-312.pyc,, +openpyxl/packaging/core.py,sha256=OSbSFGZrKYcZszcHe3LhQEyiAf2Wylwxm4_6N8WO-Yo,4061 +openpyxl/packaging/custom.py,sha256=uCEl7IwITFX2pOxiAITnvNbfsav80uHB0wXUFvjIRUQ,6738 +openpyxl/packaging/extended.py,sha256=JFksxDd67rA57n-vxg48tbeZh2g2LEOb0fgJLeqbTWM,4810 +openpyxl/packaging/interface.py,sha256=vlGVt4YvyUR4UX9Tr9xmkn1G8s_ynYVtAx4okJ6-g_8,920 +openpyxl/packaging/manifest.py,sha256=y5zoDQnhJ1aW_HPLItY_WE94fSLS4jxvfIqn_J2zJ6Q,5366 +openpyxl/packaging/relationship.py,sha256=jLhvFvDVZBRTZTXokRrrsEiLI9CmFlulhGzA_OYKM0Q,3974 +openpyxl/packaging/workbook.py,sha256=s4jl4gqqMkaUHmMAR52dc9ZoNTieuXcq1OG3cgNDYjw,6495 +openpyxl/pivot/__init__.py,sha256=c12-9kMPWlUdjwSoZPsFpmeW8KVXH0HCGpO3dlCTVqI,35 +openpyxl/pivot/__pycache__/__init__.cpython-312.pyc,, +openpyxl/pivot/__pycache__/cache.cpython-312.pyc,, +openpyxl/pivot/__pycache__/fields.cpython-312.pyc,, +openpyxl/pivot/__pycache__/record.cpython-312.pyc,, +openpyxl/pivot/__pycache__/table.cpython-312.pyc,, +openpyxl/pivot/cache.py,sha256=kKQMEcoYb9scl_CNNWfmNOTewD5S3hpBGwViMtDCyx0,27840 +openpyxl/pivot/fields.py,sha256=0CQLdTOBhYAa9gfEZb_bvkgCx8feASYp64dqFskDkqU,7057 +openpyxl/pivot/record.py,sha256=c45ft1YsPAVRneMVh_WvUQ1nZt9RJQ_josRuolKx3qE,2671 +openpyxl/pivot/table.py,sha256=riKBeb1aICXWipnhpSaSx9iqP-AkfcyOSm3Dfl407dA,40756 +openpyxl/reader/__init__.py,sha256=c12-9kMPWlUdjwSoZPsFpmeW8KVXH0HCGpO3dlCTVqI,35 +openpyxl/reader/__pycache__/__init__.cpython-312.pyc,, +openpyxl/reader/__pycache__/drawings.cpython-312.pyc,, +openpyxl/reader/__pycache__/excel.cpython-312.pyc,, +openpyxl/reader/__pycache__/strings.cpython-312.pyc,, +openpyxl/reader/__pycache__/workbook.cpython-312.pyc,, +openpyxl/reader/drawings.py,sha256=iZPok8Dc_mZMyRPk_EfDXDQvZdwfHwbYjvxfK2cXtag,2209 +openpyxl/reader/excel.py,sha256=kgStQtO1j0vV56GWaXxo3GA2EXuouGtnFrRVMocq8EY,12357 +openpyxl/reader/strings.py,sha256=oG2Mq6eBD0-ElFOxPdHTBUmshUxTNrK1sns1UJRaVis,1113 +openpyxl/reader/workbook.py,sha256=4w0LRV7qNNGHDnYd19zUgWnJOEX8tHjm3vlkxwllzv4,4352 +openpyxl/styles/__init__.py,sha256=2QNNdlz4CjhnkBQVNhZ-12Yz73_uHIinqRKWo_TjNwg,363 +openpyxl/styles/__pycache__/__init__.cpython-312.pyc,, +openpyxl/styles/__pycache__/alignment.cpython-312.pyc,, +openpyxl/styles/__pycache__/borders.cpython-312.pyc,, +openpyxl/styles/__pycache__/builtins.cpython-312.pyc,, +openpyxl/styles/__pycache__/cell_style.cpython-312.pyc,, +openpyxl/styles/__pycache__/colors.cpython-312.pyc,, +openpyxl/styles/__pycache__/differential.cpython-312.pyc,, +openpyxl/styles/__pycache__/fills.cpython-312.pyc,, +openpyxl/styles/__pycache__/fonts.cpython-312.pyc,, +openpyxl/styles/__pycache__/named_styles.cpython-312.pyc,, +openpyxl/styles/__pycache__/numbers.cpython-312.pyc,, +openpyxl/styles/__pycache__/protection.cpython-312.pyc,, +openpyxl/styles/__pycache__/proxy.cpython-312.pyc,, +openpyxl/styles/__pycache__/styleable.cpython-312.pyc,, +openpyxl/styles/__pycache__/stylesheet.cpython-312.pyc,, +openpyxl/styles/__pycache__/table.cpython-312.pyc,, +openpyxl/styles/alignment.py,sha256=wQOEtmYhPJFtnuBq0juMe5EsCp9DNSVS1ieBhlAnwWE,2198 +openpyxl/styles/borders.py,sha256=BLUTOyBbxWQzv8Kuh1u4sWfJiIPJc8QExb7nGwdSmXc,3302 +openpyxl/styles/builtins.py,sha256=cMtJverVSjdIdCckP6L-AlI0OLMRPgbQwaJWUkldA0U,31182 +openpyxl/styles/cell_style.py,sha256=8Ol5F6ktKeSqhDVF-10w5eIh7W-jkzijpPPHqqv1qDs,5414 +openpyxl/styles/colors.py,sha256=Ss3QqNS5YISVkJxlNfd4q_YSrFKdKjATWLDSu2rPMBc,4612 +openpyxl/styles/differential.py,sha256=dqEGny_ou1jC3tegBal1w_UbONyQEJXvGPURs8xWwfU,2267 +openpyxl/styles/fills.py,sha256=LmR4H00GzKDWyYjzDEayzKZN28S_muD65DvAFWlbaCI,6380 +openpyxl/styles/fonts.py,sha256=nkeiJUgKYnWaETvn51sOo9zQXJiOEJKHDTqvxt0JiBc,3516 +openpyxl/styles/named_styles.py,sha256=nfL1KPpd6b0Y0qBrGJQ15EUOebfeO1eZBQhPVpcZW-o,7254 +openpyxl/styles/numbers.py,sha256=6kK7mdBD-0xs7bjYDFNGsUAvoFvRu5wSMjOF9J5j-Go,5097 +openpyxl/styles/protection.py,sha256=BUHgARq7SjOVfW_ST53hKCUofVBEWXn3Lnn_c5n4i_I,394 +openpyxl/styles/proxy.py,sha256=ajsvzRp_MOeV_rZSEfVoti6-3tW8aowo5_Hjwp2AlfA,1432 +openpyxl/styles/styleable.py,sha256=Yl_-oPljEuFzg9tXKSSCuvWRL4L0HC5bHMFJVhex6Oc,4499 +openpyxl/styles/stylesheet.py,sha256=7kZpzyavLrOJcdZqZzl3WZTyM60CqWP8i_OQ0J_1xy0,8790 +openpyxl/styles/table.py,sha256=VexRqPPQmjRzWe1rVTOgyOQgvlCBuEYTif5MEV_0qsk,2801 +openpyxl/utils/__init__.py,sha256=wCMNXgIoA4aF4tpSuSzxm1k3SmJJGOEjtdbqdJZZG7I,324 +openpyxl/utils/__pycache__/__init__.cpython-312.pyc,, +openpyxl/utils/__pycache__/bound_dictionary.cpython-312.pyc,, +openpyxl/utils/__pycache__/cell.cpython-312.pyc,, +openpyxl/utils/__pycache__/dataframe.cpython-312.pyc,, +openpyxl/utils/__pycache__/datetime.cpython-312.pyc,, +openpyxl/utils/__pycache__/escape.cpython-312.pyc,, +openpyxl/utils/__pycache__/exceptions.cpython-312.pyc,, +openpyxl/utils/__pycache__/formulas.cpython-312.pyc,, +openpyxl/utils/__pycache__/indexed_list.cpython-312.pyc,, +openpyxl/utils/__pycache__/inference.cpython-312.pyc,, +openpyxl/utils/__pycache__/protection.cpython-312.pyc,, +openpyxl/utils/__pycache__/units.cpython-312.pyc,, +openpyxl/utils/bound_dictionary.py,sha256=zfzflQom1FqfEw8uexBqI8eExCeAWELzSk4TqqpD-w8,717 +openpyxl/utils/cell.py,sha256=P7og4c4JcSN__amIsubIMgSMlQ4SrAA5eZ0cjkoXlaQ,6967 +openpyxl/utils/dataframe.py,sha256=d3SPeb4p9YKFwlFTUWhdVUYYyMLNrd9atC6iSf2QB6w,2957 +openpyxl/utils/datetime.py,sha256=xQ8zHJFb-n4nlN6fA_fFZKHlHeNOB7El48p9-YOPvGE,4529 +openpyxl/utils/escape.py,sha256=4dgcSlSdPNk0vkJNHRUK9poEe8pn4sBIQ5Rjz-7H1Uk,790 +openpyxl/utils/exceptions.py,sha256=WT40gTyd9YUhg1MeqZNzHp9qJnL5eXzbCEb_VtHp3Kk,889 +openpyxl/utils/formulas.py,sha256=-I0zyvicBZMaAH1XzsmmEEzE4GB-NA605aArWVt9ik4,4248 +openpyxl/utils/indexed_list.py,sha256=hBsQP9gunTit7iKdMGw_tM3y5uIpXDjUx7jswbQF6Dc,1257 +openpyxl/utils/inference.py,sha256=dM1FBW_Rx_xE7P8vGo6WNhbBe-2eqpGuJj4eqdS7UjE,1583 +openpyxl/utils/protection.py,sha256=opm7GVM2ePQvpNzKT-W56u-0yP8liS9WJkxpzpG_tE0,830 +openpyxl/utils/units.py,sha256=eGpGrdzyoKlqLs99eALNC5c1gSLXRo4GdUNAqdB4wzg,2642 +openpyxl/workbook/__init__.py,sha256=yKMikN8VqoVZJcoZSVW3p9Smt88ibeqNq9NHhGBJqEM,68 +openpyxl/workbook/__pycache__/__init__.cpython-312.pyc,, +openpyxl/workbook/__pycache__/_writer.cpython-312.pyc,, +openpyxl/workbook/__pycache__/child.cpython-312.pyc,, +openpyxl/workbook/__pycache__/defined_name.cpython-312.pyc,, +openpyxl/workbook/__pycache__/external_reference.cpython-312.pyc,, +openpyxl/workbook/__pycache__/function_group.cpython-312.pyc,, +openpyxl/workbook/__pycache__/properties.cpython-312.pyc,, +openpyxl/workbook/__pycache__/protection.cpython-312.pyc,, +openpyxl/workbook/__pycache__/smart_tags.cpython-312.pyc,, +openpyxl/workbook/__pycache__/views.cpython-312.pyc,, +openpyxl/workbook/__pycache__/web.cpython-312.pyc,, +openpyxl/workbook/__pycache__/workbook.cpython-312.pyc,, +openpyxl/workbook/_writer.py,sha256=pB4s05erNEBJFT_w5LT-2DlxqXkZLOutXWVgewRLVds,6506 +openpyxl/workbook/child.py,sha256=r_5V9DNkGSYZhzi62P10ZnsO5iT518YopcTdmSvtAUc,4052 +openpyxl/workbook/defined_name.py,sha256=EAF1WvGYU4WG7dusDi29yBAr15BhkYtkF_GrFym1DDY,5394 +openpyxl/workbook/external_link/__init__.py,sha256=YOkLI226nyopB6moShzGIfBRckdQgPiFXjVZwXW-DpE,71 +openpyxl/workbook/external_link/__pycache__/__init__.cpython-312.pyc,, +openpyxl/workbook/external_link/__pycache__/external.cpython-312.pyc,, +openpyxl/workbook/external_link/external.py,sha256=LXXuej0-d0iRnwlJ-13S81kbuDxvhAWo3qfnxpsClvM,4509 +openpyxl/workbook/external_reference.py,sha256=9bKX9_QgNJxv7fEUd0G-ocXyZajMAsDzG11d0miguxY,348 +openpyxl/workbook/function_group.py,sha256=x5QfUpFdsjtbFbAJzZof7SrZ376nufNY92mpCcaSPiQ,803 +openpyxl/workbook/properties.py,sha256=vMUriu67iQU11xIos37ayv73gjq1kdHgI27ncJ3Vk24,5261 +openpyxl/workbook/protection.py,sha256=LhiyuoOchdrun9xMwq_pxGzbkysziThfKivk0dHHOLw,6008 +openpyxl/workbook/smart_tags.py,sha256=xHHXCrUPnHeRoM_eakrCOz-eCpct3Y7xKHShr9wGv7s,1181 +openpyxl/workbook/views.py,sha256=uwQqZCrRavAoBDLZIBtgz7riOEhEaHplybV4cX_TMgY,5214 +openpyxl/workbook/web.py,sha256=87B5mEZ6vfHTwywcGtcYL6u7D3RyJVDCJxV0nHZeS-w,2642 +openpyxl/workbook/workbook.py,sha256=oaErvSH1qUphUAPOZTCHj2UHyKeDqsj2DycKCDcgo7M,13232 +openpyxl/worksheet/__init__.py,sha256=c12-9kMPWlUdjwSoZPsFpmeW8KVXH0HCGpO3dlCTVqI,35 +openpyxl/worksheet/__pycache__/__init__.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/_read_only.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/_reader.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/_write_only.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/_writer.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/cell_range.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/cell_watch.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/controls.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/copier.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/custom.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/datavalidation.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/dimensions.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/drawing.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/errors.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/filters.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/formula.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/header_footer.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/hyperlink.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/merge.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/ole.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/page.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/pagebreak.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/picture.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/print_settings.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/properties.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/protection.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/related.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/scenario.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/smart_tag.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/table.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/views.cpython-312.pyc,, +openpyxl/worksheet/__pycache__/worksheet.cpython-312.pyc,, +openpyxl/worksheet/_read_only.py,sha256=6Kd4Q-73UoJDY66skRJy_ks-wCHNttlGhsDxvB99PuY,5709 +openpyxl/worksheet/_reader.py,sha256=vp_D7w4DiADMdyNrYpQglrCVvVLT9_DsSZikOd--n2c,16375 +openpyxl/worksheet/_write_only.py,sha256=yqW-DtBDDYTwGCBHRVIwkheSB7SSLO3xlw-RsXtPorE,4232 +openpyxl/worksheet/_writer.py,sha256=bDtw6BV5tdztARQEkQPprExRr8hZVFkj0DyolqxVu2k,10283 +openpyxl/worksheet/cell_range.py,sha256=YP8AUnqUFP5wOV_avMDFRSZ0Qi2p78RWFuwyyCua7m8,15013 +openpyxl/worksheet/cell_watch.py,sha256=LdxGcTmXbZ4sxm6inasFgZPld1ijdL5_ODSUvvz13DU,608 +openpyxl/worksheet/controls.py,sha256=FPLg4N94T-IL27NLg8Le_U4WYDT_6Aa25LDG_kiEDVA,2735 +openpyxl/worksheet/copier.py,sha256=0Di1qSks0g7Jtgmpc_M20O-KPCW81Yr2myC5j458nyU,2319 +openpyxl/worksheet/custom.py,sha256=CRlQ98GwqqKmEDkv8gPUCa0ApNM2Vz-BLs_-RMu3jLA,639 +openpyxl/worksheet/datavalidation.py,sha256=m-O7NOoTDr_bAfxB9xEeY5QttFiuPtzs-IFAlF0j4FE,6131 +openpyxl/worksheet/dimensions.py,sha256=HzM77FrYixiQDCugRT-C9ZpKq7GNFaGchxT73U4cisY,9102 +openpyxl/worksheet/drawing.py,sha256=2nfrLyTX0kAizPIINF12KwDW9mRnaq8hs-NrSBcWpmE,275 +openpyxl/worksheet/errors.py,sha256=KkFC4bnckvCp74XsVXA7JUCi4MIimEFu3uAddcQpjo0,2435 +openpyxl/worksheet/filters.py,sha256=8eUj2LuP8Qbz1R1gkK1c6W_UKS8-__6XlFMVkunIua0,13854 +openpyxl/worksheet/formula.py,sha256=5yuul6s1l-K_78KXHC6HrF_pLhxypoldh5jMg7zmlyY,1045 +openpyxl/worksheet/header_footer.py,sha256=91F6NUDUEwrhgeWrxG9XtDPyPD03XAtGU_ONBpkAfUc,7886 +openpyxl/worksheet/hyperlink.py,sha256=sXzPkkjl9BWNzCxwwEEaSS53J37jIXPmnnED-j8MIBo,1103 +openpyxl/worksheet/merge.py,sha256=gNOIH6EJ8wVcJpibAv4CMc7UpD7_DrGvgaCSvG2im5A,4125 +openpyxl/worksheet/ole.py,sha256=khVvqMt4GPc9Yr6whLDfkUo51euyLXfJe1p4zFee4no,3530 +openpyxl/worksheet/page.py,sha256=4jeSRcDE0S2RPzIAmA3Bh-uXRyq0hnbO5h5pJdGHbbQ,4901 +openpyxl/worksheet/pagebreak.py,sha256=XXFIMOY4VdPQCd86nGPghA6hOfLGK5G_KFuvjBNPRsw,1811 +openpyxl/worksheet/picture.py,sha256=72TctCxzk2JU8uFfjiEbTBufEe5eQxIieSPBRhU6m1Q,185 +openpyxl/worksheet/print_settings.py,sha256=k_g4fkrs9bfz-S-RIKIBGqzVgubufMdryWQ3ejXQoRI,5215 +openpyxl/worksheet/properties.py,sha256=9iXTOVC8B9C-2pp_iU5l0r5Fjf3Uzv0SIOUKRrZ2hw4,3087 +openpyxl/worksheet/protection.py,sha256=vj5M6WWC5xKiHeWS_tJqXxrlOJHJ7GpW2JdPw7r9jjE,3758 +openpyxl/worksheet/related.py,sha256=ZLDpgcrW6DWl8vvh2sSVB_r1JyG8bC8EicCBKjfssTs,335 +openpyxl/worksheet/scenario.py,sha256=VlJW4pi1OTy1cJ9m7ZxazIy8PSlo17BGpnUYixmNotQ,2401 +openpyxl/worksheet/smart_tag.py,sha256=nLbt04IqeJllk7TmNS1eTNdb7On5jMf3llfyy3otDSk,1608 +openpyxl/worksheet/table.py,sha256=gjt-jNP8dhVy8w5g-gMJpfHO-eV1EoxJy91yi-5HG64,11671 +openpyxl/worksheet/views.py,sha256=DkZcptwpbpklHILSlvK-a2LmJ7BWb1wbDcz2JVl7404,4974 +openpyxl/worksheet/worksheet.py,sha256=4JM5qjoJumtcqftHFkimtFEQrz7E2DBmXnkVo7R3WX8,27572 +openpyxl/writer/__init__.py,sha256=c12-9kMPWlUdjwSoZPsFpmeW8KVXH0HCGpO3dlCTVqI,35 +openpyxl/writer/__pycache__/__init__.cpython-312.pyc,, +openpyxl/writer/__pycache__/excel.cpython-312.pyc,, +openpyxl/writer/__pycache__/theme.cpython-312.pyc,, +openpyxl/writer/excel.py,sha256=6ioXn3hSHHIUnkW2wCyBgPA4CncO6FXL5yGSAzsqp6Y,9572 +openpyxl/writer/theme.py,sha256=5Hhq-0uP55sf_Zhw7i3M9azCfCjALQxoo7CV_9QPmTA,10320 +openpyxl/xml/__init__.py,sha256=A5Kj0GWk5XI-zJxbAL5vIppV_AgEHLRveGu8RK5c7U0,1016 +openpyxl/xml/__pycache__/__init__.cpython-312.pyc,, +openpyxl/xml/__pycache__/constants.cpython-312.pyc,, +openpyxl/xml/__pycache__/functions.cpython-312.pyc,, +openpyxl/xml/constants.py,sha256=HDNnhcj-WO9ayO4Mqwca3Au0ZTNfsDqWDtleREs_Wto,4833 +openpyxl/xml/functions.py,sha256=jBtfa8__w4gBlEPGHLGCAtJiaNKPyihTLsfmigyq2_Q,2025 diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/REQUESTED b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/WHEEL b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/WHEEL new file mode 100644 index 0000000..832be11 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.43.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/top_level.txt b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/top_level.txt new file mode 100644 index 0000000..794cc3d --- /dev/null +++ b/venv/Lib/site-packages/openpyxl-3.1.5.dist-info/top_level.txt @@ -0,0 +1 @@ +openpyxl diff --git a/venv/Lib/site-packages/openpyxl/__init__.py b/venv/Lib/site-packages/openpyxl/__init__.py new file mode 100644 index 0000000..14e8432 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/__init__.py @@ -0,0 +1,19 @@ +# Copyright (c) 2010-2024 openpyxl + +DEBUG = False + +from openpyxl.compat.numbers import NUMPY +from openpyxl.xml import DEFUSEDXML, LXML +from openpyxl.workbook import Workbook +from openpyxl.reader.excel import load_workbook as open +from openpyxl.reader.excel import load_workbook +import openpyxl._constants as constants + +# Expose constants especially the version number + +__author__ = constants.__author__ +__author_email__ = constants.__author_email__ +__license__ = constants.__license__ +__maintainer_email__ = constants.__maintainer_email__ +__url__ = constants.__url__ +__version__ = constants.__version__ diff --git a/venv/Lib/site-packages/openpyxl/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..978e54787c3aa18199bcb6053f1dad84e1a459f3 GIT binary patch literal 818 zcmZvX&u-d45XRSFV=yr#H5FA8RY?=2@&R&+Dpgeva zxc?2$S7ajt*@B&N1utc!ghZ#^v?m&(CmGTr7u}2}8}dR+Zq~~g%7)G@bjHnlJBBJC zs^0D|J8V2g0r=Amu$0CF;0IfH5%{w$d>8of7XA?U$ri2+GrHXTn>e}Ij@aNdf=7TjQF-!tCrFxCaFx{TQP^AcR>rC6#r-n8GwWfo9B7!KU3#k_z- zRlnzTC=YoWI>b9`ci_2P1jMC;@2>gkOP)#iqc!K0*pyf4z@jdf6HiRMSX)nDn9>#xahIc%`XF92ZC)W7n~$A5ut47z6erIF#d6iHvcNFKhd-l*4?C zzoUB?2mQOQy)@e)Q1czL?dnytX4Xh(!Pu9a-BK$GO`AjnJ6^zeM7i0ge&1|49W!(y zS_z2NC7)<$t`<7Q*zuhR<7zOBv#&g6_gwm#KY?BXoY01Ao)!dQoeq8s(?ugGu>pTt2%)rKzG# Sl)bUCH_v-r{Ow(NF^ zIPwv9e23Tk8h3q{*Zn$g_zm9lo4n<>X6@}4#j1Bo*#!+@GXX<6HPkCQBY@50$@ufh z*{FESBC28mn8j3G96kCzlc~;QBhnB!x%y(^GstV zlVT$>Cew$5!IFp-P;MgNl4&et(b&T~c)xJ>@WJ=(_M%0Itq`*C2%))&q_XkK{}>V~ zVw>p@5(@^Y1`E~+vFX&<1&S;wwo|U2xl=ovkm*y~Y-Zcq_!`|+!rlKE9tM+Y`d}cfU`REi98Q%y2WE6oDMUn)No7Cy)7(S|=y{-B!y<^?2>p0H8X3eSJwo&iR+$-1K-=LMUw>IyTuMcj}dg;BJx60lt Ni@U48J@wL_dH|Fbso?+s literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/_constants.py b/venv/Lib/site-packages/openpyxl/_constants.py new file mode 100644 index 0000000..e7ff6b9 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/_constants.py @@ -0,0 +1,13 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Package metadata +""" + +__author__ = "See AUTHORS" +__author_email__ = "charlie.clark@clark-consulting.eu" +__license__ = "MIT" +__maintainer_email__ = "openpyxl-users@googlegroups.com" +__url__ = "https://openpyxl.readthedocs.io" +__version__ = "3.1.5" +__python__ = "3.8" diff --git a/venv/Lib/site-packages/openpyxl/cell/__init__.py b/venv/Lib/site-packages/openpyxl/cell/__init__.py new file mode 100644 index 0000000..0c1ca3f --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/cell/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) 2010-2024 openpyxl + +from .cell import Cell, WriteOnlyCell, MergedCell +from .read_only import ReadOnlyCell diff --git a/venv/Lib/site-packages/openpyxl/cell/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/cell/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fce7c6ff047719cc1c2dc5441e67c4d3fea78b27 GIT binary patch literal 326 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 m=-Z%L$;OQrNFQ0V@e0)Y|MdzX~&+uQV=5KcZ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/cell/__pycache__/cell.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/cell/__pycache__/cell.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5a99a080b67e3c5440f0463d56a76a5c656d333 GIT binary patch literal 12345 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".format(self.parent.title, self.coordinate) + + def check_string(self, value): + """Check string coding, length, and line break character""" + if value is None: + return + # convert to str string + if not isinstance(value, str): + value = str(value, self.encoding) + value = str(value) + # string must never be longer than 32,767 characters + # truncate if necessary + value = value[:32767] + if next(ILLEGAL_CHARACTERS_RE.finditer(value), None): + raise IllegalCharacterError(f"{value} cannot be used in worksheets.") + return value + + def check_error(self, value): + """Tries to convert Error" else N/A""" + try: + return str(value) + except UnicodeDecodeError: + return u'#N/A' + + + def _bind_value(self, value): + """Given a value, infer the correct data type""" + + self.data_type = "n" + t = type(value) + try: + dt = _TYPES[t] + except KeyError: + dt = get_type(t, value) + + if dt is None and value is not None: + raise ValueError("Cannot convert {0!r} to Excel".format(value)) + + if dt: + self.data_type = dt + + if dt == 'd': + if not is_date_format(self.number_format): + self.number_format = get_time_format(t) + + elif dt == "s" and not isinstance(value, CellRichText): + value = self.check_string(value) + if len(value) > 1 and value.startswith("="): + self.data_type = 'f' + elif value in ERROR_CODES: + self.data_type = 'e' + + self._value = value + + + @property + def value(self): + """Get or set the value held in the cell. + + :type: depends on the value (string, float, int or + :class:`datetime.datetime`) + """ + return self._value + + @value.setter + def value(self, value): + """Set the value and infer type and display options.""" + self._bind_value(value) + + @property + def internal_value(self): + """Always returns the value for excel.""" + return self._value + + @property + def hyperlink(self): + """Return the hyperlink target or an empty string""" + return self._hyperlink + + + @hyperlink.setter + def hyperlink(self, val): + """Set value and display for hyperlinks in a cell. + Automatically sets the `value` of the cell with link text, + but you can modify it afterwards by setting the `value` + property, and the hyperlink will remain. + Hyperlink is removed if set to ``None``.""" + if val is None: + self._hyperlink = None + else: + if not isinstance(val, Hyperlink): + val = Hyperlink(ref="", target=val) + val.ref = self.coordinate + self._hyperlink = val + if self._value is None: + self.value = val.target or val.location + + + @property + def is_date(self): + """True if the value is formatted as a date + + :type: bool + """ + return self.data_type == 'd' or ( + self.data_type == 'n' and is_date_format(self.number_format) + ) + + + def offset(self, row=0, column=0): + """Returns a cell location relative to this cell. + + :param row: number of rows to offset + :type row: int + + :param column: number of columns to offset + :type column: int + + :rtype: :class:`openpyxl.cell.Cell` + """ + offset_column = self.col_idx + column + offset_row = self.row + row + return self.parent.cell(column=offset_column, row=offset_row) + + + @property + def comment(self): + """ Returns the comment associated with this cell + + :type: :class:`openpyxl.comments.Comment` + """ + return self._comment + + + @comment.setter + def comment(self, value): + """ + Assign a comment to a cell + """ + + if value is not None: + if value.parent: + value = copy(value) + value.bind(self) + elif value is None and self._comment: + self._comment.unbind() + self._comment = value + + +class MergedCell(StyleableObject): + + """ + Describes the properties of a cell in a merged cell and helps to + display the borders of the merged cell. + + The value of a MergedCell is always None. + """ + + __slots__ = ('row', 'column') + + _value = None + data_type = "n" + comment = None + hyperlink = None + + + def __init__(self, worksheet, row=None, column=None): + super().__init__(worksheet) + self.row = row + self.column = column + + + def __repr__(self): + return "".format(self.parent.title, self.coordinate) + + coordinate = Cell.coordinate + _comment = comment + value = _value + + +def WriteOnlyCell(ws=None, value=None): + return Cell(worksheet=ws, column=1, row=1, value=value) diff --git a/venv/Lib/site-packages/openpyxl/cell/read_only.py b/venv/Lib/site-packages/openpyxl/cell/read_only.py new file mode 100644 index 0000000..2eec09e --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/cell/read_only.py @@ -0,0 +1,136 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.cell import Cell +from openpyxl.utils import get_column_letter +from openpyxl.utils.datetime import from_excel +from openpyxl.styles import is_date_format +from openpyxl.styles.numbers import BUILTIN_FORMATS, BUILTIN_FORMATS_MAX_SIZE + + +class ReadOnlyCell: + + __slots__ = ('parent', 'row', 'column', '_value', 'data_type', '_style_id') + + def __init__(self, sheet, row, column, value, data_type='n', style_id=0): + self.parent = sheet + self._value = None + self.row = row + self.column = column + self.data_type = data_type + self.value = value + self._style_id = style_id + + + def __eq__(self, other): + for a in self.__slots__: + if getattr(self, a) != getattr(other, a): + return + return True + + def __ne__(self, other): + return not self.__eq__(other) + + + def __repr__(self): + return "".format(self.parent.title, self.coordinate) + + + @property + def coordinate(self): + column = get_column_letter(self.column) + return "{1}{0}".format(self.row, column) + + + @property + def coordinate(self): + return Cell.coordinate.__get__(self) + + + @property + def column_letter(self): + return Cell.column_letter.__get__(self) + + + @property + def style_array(self): + return self.parent.parent._cell_styles[self._style_id] + + + @property + def has_style(self): + return self._style_id != 0 + + + @property + def number_format(self): + _id = self.style_array.numFmtId + if _id < BUILTIN_FORMATS_MAX_SIZE: + return BUILTIN_FORMATS.get(_id, "General") + else: + return self.parent.parent._number_formats[ + _id - BUILTIN_FORMATS_MAX_SIZE] + + @property + def font(self): + _id = self.style_array.fontId + return self.parent.parent._fonts[_id] + + @property + def fill(self): + _id = self.style_array.fillId + return self.parent.parent._fills[_id] + + @property + def border(self): + _id = self.style_array.borderId + return self.parent.parent._borders[_id] + + @property + def alignment(self): + _id = self.style_array.alignmentId + return self.parent.parent._alignments[_id] + + @property + def protection(self): + _id = self.style_array.protectionId + return self.parent.parent._protections[_id] + + + @property + def is_date(self): + return Cell.is_date.__get__(self) + + + @property + def internal_value(self): + return self._value + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + if self._value is not None: + raise AttributeError("Cell is read only") + self._value = value + + +class EmptyCell: + + __slots__ = () + + value = None + is_date = False + font = None + border = None + fill = None + number_format = None + alignment = None + data_type = 'n' + + + def __repr__(self): + return "" + +EMPTY_CELL = EmptyCell() diff --git a/venv/Lib/site-packages/openpyxl/cell/rich_text.py b/venv/Lib/site-packages/openpyxl/cell/rich_text.py new file mode 100644 index 0000000..373e263 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/cell/rich_text.py @@ -0,0 +1,202 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +RichText definition +""" +from copy import copy +from openpyxl.compat import NUMERIC_TYPES +from openpyxl.cell.text import InlineFont, Text +from openpyxl.descriptors import ( + Strict, + String, + Typed +) + +from openpyxl.xml.functions import Element, whitespace + +class TextBlock(Strict): + """ Represents text string in a specific format + + This class is used as part of constructing a rich text strings. + """ + font = Typed(expected_type=InlineFont) + text = String() + + def __init__(self, font, text): + self.font = font + self.text = text + + + def __eq__(self, other): + return self.text == other.text and self.font == other.font + + + def __str__(self): + """Just retun the text""" + return self.text + + + def __repr__(self): + font = self.font != InlineFont() and self.font or "default" + return f"{self.__class__.__name__} text={self.text}, font={font}" + + + def to_tree(self): + el = Element("r") + el.append(self.font.to_tree(tagname="rPr")) + t = Element("t") + t.text = self.text + whitespace(t) + el.append(t) + return el + +# +# Rich Text class. +# This class behaves just like a list whose members are either simple strings, or TextBlock() instances. +# In addition, it can be initialized in several ways: +# t = CellRFichText([...]) # initialize with a list. +# t = CellRFichText((...)) # initialize with a tuple. +# t = CellRichText(node) # where node is an Element() from either lxml or xml.etree (has a 'tag' element) +class CellRichText(list): + """Represents a rich text string. + + Initialize with a list made of pure strings or :class:`TextBlock` elements + Can index object to access or modify individual rich text elements + it also supports the + and += operators between rich text strings + There are no user methods for this class + + operations which modify the string will generally call an optimization pass afterwards, + that merges text blocks with identical formats, consecutive pure text strings, + and remove empty strings and empty text blocks + """ + + def __init__(self, *args): + if len(args) == 1: + args = args[0] + if isinstance(args, (list, tuple)): + CellRichText._check_rich_text(args) + else: + CellRichText._check_element(args) + args = [args] + else: + CellRichText._check_rich_text(args) + super().__init__(args) + + + @classmethod + def _check_element(cls, value): + if not isinstance(value, (str, TextBlock, NUMERIC_TYPES)): + raise TypeError(f"Illegal CellRichText element {value}") + + + @classmethod + def _check_rich_text(cls, rich_text): + for t in rich_text: + CellRichText._check_element(t) + + @classmethod + def from_tree(cls, node): + text = Text.from_tree(node) + if text.t: + return (text.t.replace('x005F_', ''),) + s = [] + for r in text.r: + t = "" + if r.t: + t = r.t.replace('x005F_', '') + if r.rPr: + s.append(TextBlock(r.rPr, t)) + else: + s.append(t) + return cls(s) + + # Merge TextBlocks with identical formatting + # remove empty elements + def _opt(self): + last_t = None + l = CellRichText(tuple()) + for t in self: + if isinstance(t, str): + if not t: + continue + elif not t.text: + continue + if type(last_t) == type(t): + if isinstance(t, str): + last_t += t + continue + elif last_t.font == t.font: + last_t.text += t.text + continue + if last_t: + l.append(last_t) + last_t = t + if last_t: + # Add remaining TextBlock at end of rich text + l.append(last_t) + super().__setitem__(slice(None), l) + return self + + + def __iadd__(self, arg): + # copy used here to create new TextBlock() so we don't modify the right hand side in _opt() + CellRichText._check_rich_text(arg) + super().__iadd__([copy(e) for e in list(arg)]) + return self._opt() + + + def __add__(self, arg): + return CellRichText([copy(e) for e in list(self) + list(arg)])._opt() + + + def __setitem__(self, indx, val): + CellRichText._check_element(val) + super().__setitem__(indx, val) + self._opt() + + + def append(self, arg): + CellRichText._check_element(arg) + super().append(arg) + + + def extend(self, arg): + CellRichText._check_rich_text(arg) + super().extend(arg) + + + def __repr__(self): + return "CellRichText([{}])".format(', '.join((repr(s) for s in self))) + + + def __str__(self): + return ''.join([str(s) for s in self]) + + + def as_list(self): + """ + Returns a list of the strings contained. + The main reason for this is to make editing easier. + """ + return [str(s) for s in self] + + + def to_tree(self): + """ + Return the full XML representation + """ + container = Element("is") + for obj in self: + if isinstance(obj, TextBlock): + container.append(obj.to_tree()) + + else: + el = Element("r") + t = Element("t") + t.text = obj + whitespace(t) + el.append(t) + container.append(el) + + return container + diff --git a/venv/Lib/site-packages/openpyxl/cell/text.py b/venv/Lib/site-packages/openpyxl/cell/text.py new file mode 100644 index 0000000..54923dd --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/cell/text.py @@ -0,0 +1,184 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Richtext definition +""" + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Alias, + Typed, + Integer, + Set, + NoneSet, + Bool, + String, + Sequence, +) +from openpyxl.descriptors.nested import ( + NestedBool, + NestedInteger, + NestedString, + NestedText, +) +from openpyxl.styles.fonts import Font + + +class PhoneticProperties(Serialisable): + + tagname = "phoneticPr" + + fontId = Integer() + type = NoneSet(values=(['halfwidthKatakana', 'fullwidthKatakana', + 'Hiragana', 'noConversion'])) + alignment = NoneSet(values=(['noControl', 'left', 'center', 'distributed'])) + + def __init__(self, + fontId=None, + type=None, + alignment=None, + ): + self.fontId = fontId + self.type = type + self.alignment = alignment + + +class PhoneticText(Serialisable): + + tagname = "rPh" + + sb = Integer() + eb = Integer() + t = NestedText(expected_type=str) + text = Alias('t') + + def __init__(self, + sb=None, + eb=None, + t=None, + ): + self.sb = sb + self.eb = eb + self.t = t + + +class InlineFont(Font): + + """ + Font for inline text because, yes what you need are different objects with the same elements but different constraints. + """ + + tagname = "RPrElt" + + rFont = NestedString(allow_none=True) + charset = Font.charset + family = Font.family + b =Font.b + i = Font.i + strike = Font.strike + outline = Font.outline + shadow = Font.shadow + condense = Font.condense + extend = Font.extend + color = Font.color + sz = Font.sz + u = Font.u + vertAlign = Font.vertAlign + scheme = Font.scheme + + __elements__ = ('rFont', 'charset', 'family', 'b', 'i', 'strike', + 'outline', 'shadow', 'condense', 'extend', 'color', 'sz', 'u', + 'vertAlign', 'scheme') + + def __init__(self, + rFont=None, + charset=None, + family=None, + b=None, + i=None, + strike=None, + outline=None, + shadow=None, + condense=None, + extend=None, + color=None, + sz=None, + u=None, + vertAlign=None, + scheme=None, + ): + self.rFont = rFont + self.charset = charset + self.family = family + self.b = b + self.i = i + self.strike = strike + self.outline = outline + self.shadow = shadow + self.condense = condense + self.extend = extend + self.color = color + self.sz = sz + self.u = u + self.vertAlign = vertAlign + self.scheme = scheme + + +class RichText(Serialisable): + + tagname = "RElt" + + rPr = Typed(expected_type=InlineFont, allow_none=True) + font = Alias("rPr") + t = NestedText(expected_type=str, allow_none=True) + text = Alias("t") + + __elements__ = ('rPr', 't') + + def __init__(self, + rPr=None, + t=None, + ): + self.rPr = rPr + self.t = t + + +class Text(Serialisable): + + tagname = "text" + + t = NestedText(allow_none=True, expected_type=str) + plain = Alias("t") + r = Sequence(expected_type=RichText, allow_none=True) + formatted = Alias("r") + rPh = Sequence(expected_type=PhoneticText, allow_none=True) + phonetic = Alias("rPh") + phoneticPr = Typed(expected_type=PhoneticProperties, allow_none=True) + PhoneticProperties = Alias("phoneticPr") + + __elements__ = ('t', 'r', 'rPh', 'phoneticPr') + + def __init__(self, + t=None, + r=(), + rPh=(), + phoneticPr=None, + ): + self.t = t + self.r = r + self.rPh = rPh + self.phoneticPr = phoneticPr + + + @property + def content(self): + """ + Text stripped of all formatting + """ + snippets = [] + if self.plain is not None: + snippets.append(self.plain) + for block in self.formatted: + if block.t is not None: + snippets.append(block.t) + return u"".join(snippets) diff --git a/venv/Lib/site-packages/openpyxl/chart/_3d.py b/venv/Lib/site-packages/openpyxl/chart/_3d.py new file mode 100644 index 0000000..1651a99 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/_3d.py @@ -0,0 +1,105 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors import Typed, Alias +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors.nested import ( + NestedBool, + NestedInteger, + NestedMinMax, +) +from openpyxl.descriptors.excel import ExtensionList +from .marker import PictureOptions +from .shapes import GraphicalProperties + + +class View3D(Serialisable): + + tagname = "view3D" + + rotX = NestedMinMax(min=-90, max=90, allow_none=True) + x_rotation = Alias('rotX') + hPercent = NestedMinMax(min=5, max=500, allow_none=True) + height_percent = Alias('hPercent') + rotY = NestedInteger(min=-90, max=90, allow_none=True) + y_rotation = Alias('rotY') + depthPercent = NestedInteger(allow_none=True) + rAngAx = NestedBool(allow_none=True) + right_angle_axes = Alias('rAngAx') + perspective = NestedInteger(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('rotX', 'hPercent', 'rotY', 'depthPercent', 'rAngAx', + 'perspective',) + + def __init__(self, + rotX=15, + hPercent=None, + rotY=20, + depthPercent=None, + rAngAx=True, + perspective=None, + extLst=None, + ): + self.rotX = rotX + self.hPercent = hPercent + self.rotY = rotY + self.depthPercent = depthPercent + self.rAngAx = rAngAx + self.perspective = perspective + + +class Surface(Serialisable): + + tagname = "surface" + + thickness = NestedInteger(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + pictureOptions = Typed(expected_type=PictureOptions, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('thickness', 'spPr', 'pictureOptions',) + + def __init__(self, + thickness=None, + spPr=None, + pictureOptions=None, + extLst=None, + ): + self.thickness = thickness + self.spPr = spPr + self.pictureOptions = pictureOptions + + +class _3DBase(Serialisable): + + """ + Base class for 3D charts + """ + + tagname = "ChartBase" + + view3D = Typed(expected_type=View3D, allow_none=True) + floor = Typed(expected_type=Surface, allow_none=True) + sideWall = Typed(expected_type=Surface, allow_none=True) + backWall = Typed(expected_type=Surface, allow_none=True) + + def __init__(self, + view3D=None, + floor=None, + sideWall=None, + backWall=None, + ): + if view3D is None: + view3D = View3D() + self.view3D = view3D + if floor is None: + floor = Surface() + self.floor = floor + if sideWall is None: + sideWall = Surface() + self.sideWall = sideWall + if backWall is None: + backWall = Surface() + self.backWall = backWall + super(_3DBase, self).__init__() diff --git a/venv/Lib/site-packages/openpyxl/chart/__init__.py b/venv/Lib/site-packages/openpyxl/chart/__init__.py new file mode 100644 index 0000000..ecc4d8b --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/__init__.py @@ -0,0 +1,19 @@ +# Copyright (c) 2010-2024 openpyxl + +from .area_chart import AreaChart, AreaChart3D +from .bar_chart import BarChart, BarChart3D +from .bubble_chart import BubbleChart +from .line_chart import LineChart, LineChart3D +from .pie_chart import ( + PieChart, + PieChart3D, + DoughnutChart, + ProjectedPieChart +) +from .radar_chart import RadarChart +from .scatter_chart import ScatterChart +from .stock_chart import StockChart +from .surface_chart import SurfaceChart, SurfaceChart3D + +from .series_factory import SeriesFactory as Series +from .reference import Reference diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/_3d.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/_3d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ed25caee3775d82e9d293b3004e431aaff7a862 GIT binary patch literal 3440 zcmb7GO>7(25q?YVE|>rMp+t%LG5wQRY-%N`lBQOZ)VAoqRA!AzY1{>Y?V9@}ZN2>I z+m%8ZDoPXr%0mJK5DFXZMTa1;U>|(UG3d1y7i9o)VFM|8(#?jHI_Slnc_i18qDvpa z*?BYbcHW!!&CLEi8VwN``WGLrq$7m<8z;RXb(!720CR^J#1Je}6jY(;Q+)!?eU`r{ zsv_t8mQ<8gxfoCbMMYJ(OtgZ$LTH7=CPmK*KxS4$3Erp%3Wrq|5UHN6T;qZg|VE!k$dG;i9@j(`pXH+J1DIIE2Q zqT+xCT?}4kdS%5d=+<>su2ANf)Gl<+(V<=t{{!d=T~|QIN#o%`YVoeDELf zEFkRg=KU7^AQ_;8AdBAjb$6LCV(L(k?Ee}4M&E{@4%gzD0ayN&Nk5*+y7C%-nqRzl z@nT1X#fxw){-Rj|qF3FJZdv7zwNkl6U6GZY8#@?2a}R>yDl6A1E6|d|HNV~#*dXX! znVl~!pRaEF+$gP9XaVk5a{vZhyDhT>7_ng_Ni>fbwBq#M#70pR24fpnnrk#yP(aih zcsc~-?hPP!$hxpjw4RQv`(W0+B|_HyFzZGGW+KeGaE6%#GqJaDU4~f?6{JSCg&Z3P zWkzvDn_5eUcFZO~$2ZC*fpcYAb>?ly#(k!{x#qIoY%D( zW4cmv6-_fsrlV=Mu7ChRwW)XCEUGBnx{KMA%*((s735+i&zKGhJL%4lnN z9H!yc*sBfkYh`2?){snKCk~I?4&G62F_+6E(N{??QcZJ1npP|us}}MRP5a%dZgn*Q zM_)#kVGKIq!sxo8ss@Cg@ilsB z8C>gCYV)`=yiFEFf``T(QHvJgt+uAIQy|(V>=jg>L=x)}JfQtKkPY%pY`A{;U*Y84 zxvgJ5%r?Vk>)Cey@MmkA6ZH?;@v$vo%YNuIX^Q}s*jKZ@6&?f}7uNKIJ+`z&r zTha^E4cHxKk&VFKSPBSaQRO<@_Pap`>hi4;wQcq`%43xS#XDEm^owoj<&@dj7&e90$Y|r@&hEVA>kLHwA zT618tH<5dZ?HQaR!M}~A5wV>FZ1+vvOEmkY>sQ<1zDLJ?^rh1bX92aTV_WiH&pZ;7 zfa`mcUuBy^R{`1kp!v<4&~1AALu6uZ9BbGX6c!1npabsE8XB6mR7V`?|wxerntzZZBb z^5pA2u=3FCS^0R2!uRp9?myDX&s$e7$Dwr{X(jTO=J{|CReU&DF8Ej{pPnS7=Usr- z#?qk31UuCbD_8!_|ie%(YM)AexP*y?a%ES((D1b#X z$_3~duYtPLRd}=T!o$v?!aF7pgB$IhwLmRP(=r0ff{~2?IM+Ebj~J2ID6#zbRwtlf4Pi(!@>pS~+NXOBMR&oqmMQZYSa6p=R zMu2p357UnFfYoLXFM5C%XFn1i%JZI%)RCb&v;aT0^9na+n4XaMw z|Czq7H)b+s***>PL@r>vb;M4XWV4XH8{98!3jTvo4L~+vB(e#iuqISiVoQl_CAt%B zywW>LvN@Qq1XC4SO109s7S)@PjtZ^{o=Q7XxvO?{mEvWk!%ADyRhe>GDa&P5>9o>% zpve`L=w{kt0Ao-dWnYQy(syCW+OAv${VTeHi2l;iEB_ewW&ZmliiYF;kw2nvjfho0 zB=aMh(;yaUB4POcIh&pP2l2$u;+#E8X?R9YS>`7xo2847d|QujI|$-goCm=$T@>bP zkwkOO-pDQJsNP%l9K!Dg#`wC8@b)EodVwBaqT#jC!p0SX@W(}X>jFKwK#wlb%b#fH KJ9;1=!mfYrB?lG& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..500fb138c67cb9806438c8fe7dab64dd5bbbea8d GIT binary patch literal 8515 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 L_>{wi3Do}p24l$_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/bar_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/bar_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5a6abc808b7e2defd1bb1c38ec051ed1ff776ab GIT binary patch literal 5003 zcmd5=-ER}w6~E(;@%UrxI8GeLPMm}dUCfrSUD&p;Enf))XvnTg&`LwPqrr1Y9A<3q zoe3nAR(?P#Xm`6vs9heTs;w5mL!TC_P-4j9xRXq`4k8`pk@yG5eK%Gpl6HoRZ^s#27FKl|imYjl4Oe3~@bX z44Wg$2-js}oB4+FhCqB|lIZcPL{HG3JAQX>$|y&>08P@-7P_6I-GHX(C{5o9G)I49 zxu?+k7>$D9#7Q+>Kprl+axgk2NWh^z7?o1?siV{X@}Qu&m&^cYTv z6nsv?1t+!YVY9MWw!Nj_zet&(RpFP1$LBR>AJHrdMo8T=!PS5x&Cn(L@KVWgqSK2e z?5xO*2yT*EuFj`UmC6)%k(y*$b-q;8j1O3)N|_DA02bW|s7-+b$~tKBgl20~+Bs_A zhKsHw@l^^WF8|!QDYq0)PhfK+6_!)Eq?8uY|Ty zAwVTv)Wy4@JHF=3FklfH1x#vTF~DRR--IOq3+mz4Z|Kq^N>Ue;?lAHG>9K3%yr4&~ zhLzMcvLq-yr%6F}Wc7%~TF!O+=QQT{ixuNGc;cdFEKLvjq^p z5WXN+geyb^-ECKVU^P#IkSl($n%)H~09G@nzzTxpoh-3&P2R4Du8_|%1bC!Gu86-D zehy5sOm6$8Z<9iZzc2eH3}m}djG@4Hbb{6*Y|fEXwNx(Is#=hofJKe-ub$z%aLEa) zYSGXvOI0liRvC6%?O*4{_s^bz{adp$6xia3tCswPqpa%hly2V|Nh~YBwCM%C)iTGTQ^c@N#-nK#X~B z|2Fhl-v#k?jXdcheS_BmpGF&*VR*=m>?k}EjZ_*QQlmEukH`Z_z8{}=cz38H{W>QskBC2Xu^hE>pn5urfs2Oe#!_#m*hi-8KJaV|( zW7xxeA407k1wREmN|r;x&m)5V;puGQ+SH&Xgfci9EO0FFfE$kJ1xO3`7>d*|RQ0yN zz742_VRVRn2bUc5#0Yl$7{u3C$s;+v5?ool_0v^(ckS4EwChIZlY_O1^+e{MMA)|L zIT5;c*N#6*=2rIpZelgLuXb`h(!G)fJ+iMhz8*`i$oEE9V+U(T*OTcRmu}{3CpS`) zwW*C%rZ)9NB>nkDc6(!BxY66!=*zu`%E6(h1O&r_;jgqcOYMXgZ)YiB20slf@H-S{ zwlyUPIC`|BDI(zU4iHQw1UTHlolTJd@9solJZH2!%?>3BycKI%GFWk%(2+Ym2JGTk zaue3gvDDp{jM~GI-Zmr+zaOKZqv^rRfGB+}Rt#}g6oC~poE7_l6(vXVNYRlXLpVLo zuma44NZ1Jv;6iCmtA1G0?Rh6uajz-hK+5<%;{>#&6M7Mu$!jf^`Vx@WV<{Wsnm5l= zTk}*~Z;K!8#1?ZggLt!3o_1XXj@!}XxS+>z470uvWyj#bCQ%$m(F4K}msAbzUDnHu zW!K1Z!{9e4dk4p2HUUfSMSb%!jtE!xlx4Gbv5)5$ZnQ~wZkFNf%SrDrT4ZzvVCyId zB%?U#AK@(2mxo8J$w?2=`I`%1M<1j|Zknz#aC4q39n8eDrx1AjOIUDvdb*Hh`#@v+ zQM?Dj3EA2l(vX|w zC=P>Yr<`#FQ5?dK-+%zh*@$OqlN)k&O&+PsBei3V#K2l&dp)tecD#|yuO$ohWTAGl z5$Rit2x6js7XE{IR@{Rt%MmFEb47><$ zCMSIFt;y;4|3~CRBMWJG(T=7>0fz#hvnesaG2}a%A_G3q0fMQ-fu<5(nkq&dC^YTEG75~ian?hLC#d5)`!xvvgAm` zWusKqp)LwR!J(NY-HA07K8g*)o48cVFu|cx)%H+ z^t>L+ZmtDw%v9dI;{wh_4(H95J*};`#nLvWKW}Zlt@Uioci!w)r~&r^S#GW`UG9}# zLQ!A>JBy-4z@6lQi#g(Dmxnp^{t(A={*~JJw__9xdAJuw7#z)Q8o z_8#lU`v0-2ptW>q(18)q=aPLnO%nw7Io~_0)elnPiOhkd1$1rl8>{i3a z=n|Ci3^UNlZ8^aGN@e`$qqrFVrobd;ahw%xdr3E5FvT6w{d8j8X!zAVI^!`1#UIo~ z{DS9qI}Z)40UVKYm&Ncd0fT>ZxF0O10AX2#g9iS^!ToOG0gg8(<57d(ORgL76U33e z=YA_4U?!MwixR5@;)!1ngs(&*y!XN<3cjxhiZ~J8eQCbv@&hIjA^(tM{z?wsCkG#r vHy@HL|3Ca(91w^n;H;C~dH+CP?kd(rV)!!j@gz%xn?| z`QQUmgVa_?Rn?xV9I7f6960pA|4^wCst?YnsGzEc+&~ls_0;!vy`d=_x=G%=-|?64ZP zBWlEss!>~3Wjm(ET%Vv7w-ai@)k9X&R#e6AQ~T_cngUzch*VTb9 zvo4mcoSj$mt{$@n?Sfj6NPt`*M*Jo*5;T1$=$%g;T27Xf4Fn}gBxfiyb<5=XoJC7f z5uROcP(uV~s3Rhm%-SWrDMDxKbxTAq)*L!dnFyb;Oq~mPhF)KwwJL=u%K4^4Yuv2Y zrcLgYfJ|`oNMhA_m5ix6lDcDtl+q$` zc3}>3>3M{7Ms*=ALAc1GZY>~PYzWszyxmH&h%f4Fd9rTR85coL85_oV*_(g!oPVyF zs%}xy$FJ6x%5>g4I0tOrpdZl&qny?pE<$?qqEU@O1pmPbNWkB-UqE~ z7+BbD6qr=D2gP0#`%vshkpUqhO-;v37FqVjFkb+Yg{*02&2%)aln^0Ktt`jXHBEt1QymVrAN#t8mkyhZ=hInm$i?rQV>m#&Xj-T*bC=*ee^&1rv>Bb_BM) zk@d>Ot@8>0oeskcryyRm$&)-O?pq0cp6U+dVUWAIVHo1w!YB+%x43^L)R7C_k#QW0 z{`gydY?a+R+R2{)uf%_ltlWw|kP8pwk#CRwDvvyajYvr@GhmUF-KVq@6I|16s%avw zX?ERMuuxBG+Vut9>dizQeI8ZT2P-`SkaRYH!sQl=l3@*aEMxtMI3~~SiQJ=I!TFcm zClR^@fW)w)D6kaRAruoJ;21y;bXfPs4o z^S7728UcsY(CTa_b+G;3dS+zxjkP`CkU7=ZW z*i2``yPgsd?1cXs<W5}x*e%-rivQvdrbxRHM7*28`Vl~LG&xIy+Pn20ziuUo zu!SE`uZ&#Yuu#2MM=pi@wpX9;vI_u_WPTdNlb|F?f0C1%0a*%c5)e;OJkJp6_+}u4 g5XAE&kw$(e2Og3g56S3Xk%Q8%+ok6O26u;l0MHIy)Bpeg literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/chartspace.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/chartspace.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a6f2f04c7367006093bae309e7b7b56459804ea GIT binary patch literal 6008 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 I1V0nZzssy#Z~y=R literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/error_bar.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/error_bar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc625a4f892e77dc5cd456d3a0e604c333ae6572 GIT binary patch literal 2110 zcmZ`)O>7%Q6rQzr*Xy-6j^q5Vq>9QW2-#Dy0? zC;e1l*oO2~KOLC18D#8CkhQacWm|x2Sog<*oSld?$-z;rw|;><|S>>*AO=j>7%J^RBGIDcEQkG03k1)g4^G^AHt%6N*<*il+s zX~UK4+pgavjO#G4?9pT{lcfiqXhIs1^al}`J7`DQ zK@NCv+ett)NEU>4k`N7~gh+*GP%aQ@5Dn80?dT8<%NXsXAks%`8W2Ir$E^)VsXTW8 z`Vx%F&yEkUAVTr&WfP7}{F~1l_<#AJTPs>)5feu~HERECEM2VLV1%;j^$_F5_0^^7 zlFMo?CQwTI}lvC-y+<9Ky1a-3TeAa$Hzi$m-zd=I+>rh^_&qnYDhsb6RMrFrOb!*2Ez zL{@)t7P@qQssx?cFHA#cNbsBV0nA6`bcN19Pv^i?WGl~!&FgMJ9EY2Z6NI?w3qR{P zpEq59Fp`3l6fRAR=`w|cE2+fEwDU{HijtL_& zEtV`RJgHkwctSj0*nIx|qJ|hQi(&XW;*$VMg*gs=6`-FH6&FQc5hg!0;8C>XV$V9?S=}F>+THp#*ZE*SU;6#UOTGN%&WHQi{O;KY*^`|W34Ywm ze*$1;e0T0a=0sgOz1MrzyPegCg<5Crv4M)m`*WxJa|`{_iT-q{ zKXa@^qDR*VlP&Q*bD=!Ic2En;}qsn>`?$`&C>M}Iw3lpCKsibtgeqU5Nk zG%AHG9mQNEts3#=wew>~65>ZF&I*|TQfVP5&&aA^@()QW4lmi3+aQcem8C>)iv35j zapO{)ewXRnFd!Zib^*-eq@pNKb)>xYcS2JV2MEm5F{He4I6U(QI`c$7qZD_uPZ4x- G;eP?zPZkRR literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/label.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/label.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40f39105e400f7cd524b3ac7f6e79132462fdb08 GIT binary patch literal 4529 zcmcgv&2JmW6`v)SA4_s6S|TZlk|=-3u9@1hqbdgK)UIREQd}#HP$@;bP{XdcV~Ni4 zBeN@8GK69e1}dXbBq}^{JL4*cY&HOFkREEVy*3*HR&HYZ*2AfuZ}7&Hz(ezt3P-Qo`v-?)u5+*WzD2TBVQ`c<_$9?aydf{lWLh#kzl6IV5K0t5BZ|vKs9O^>*HiZsm(xQLf%8zWCOj1zoDVp^=6Ql6Ls2BVPoSkw z(C*`H^a%l$mx<>4TzKkluwlEG)WAJ}Bk-I+gMpoBV_+BBn7#u{^Z*k(z{C$Q{lLKb zn?@f1#zO~NR+i9$%8*35{j{(q-w~AI^-!vZhqGzbRA<#Cs$W(Oy1)b1ORS)pQzeb2 zTs)xadg)fS2wTo2)r9R`S~clo7nkW;ndZP7vL?6->xH+>MWZ~&xM;4;v6RGpOW-Zj zd6NrE+?_KS_vVW@1oz~NSBe@JbnY#!ns$|O!30HzTiH(-vk94(qW zjNLA;E+CpywztYoAol|_C()$PyoKh6XilLy4TgImXlD)6 zz&CTarTpjPsq>2;8I&1|3nfh(pP!yuoKlS(yjh6-8{jy`q6U7K%@@igW>U6zlNN6- z&gPdEjl4-um(|=S>M}JJK_`mk^)>xWZbfD086Ev}yu8l+*=)X;H?!H>{jCl>UT?q| z8XtqP$jc<@AK4WD5UfQ9;3Cy8{YgNf+Q?g*V%49h?ZcrH2nTBI*W@YWhiaqacpa_{ z9^Dl0g?C{Dl9DscB{hQcD}wK3vpkT^7E0Qxj`dJB`{}BxJ1q=1$$9^{%}hpP`#1Uk z?^`~omJHvt?fyJ$!pnc7qYS;li3xwX1n&@3o1ss9-_2y`TPEAKI5bgwz~f`visA3(?UIu=+10M!H*@5o?{%{9A0z7JTTTu=Hj|$XQlwRObc-o56 zr@5d7g{ZCE2CPIiag$sZH1{1ziEWZKL5a_kl!r@=Q;mywn84xU&TDJAh7iNe7-lGq zyXfM7653_ltnV$k3le@00!$O~Antz=K7%B0oji7B*t>9N%FTWX7w$1u;UKi*B_*;m zKsmhYlUrQMW^=k~Ks*^DG=NrGPB7unw|g6tZK&68fH!b^zOzWJFAh58|GQtl>#O(& zD*oidiLd=h+apr~!zHEq*(6-pJ7~^<;XYGcMx9}}LVF@k;QkMKZ>s}4kI%ztb9sMJ zIjZZ~ES%M8U=2L@E;)<4fL+o23>%(-`R)#R9*#nw2l{`1#+rIA4{ggwEAmlmx)vPV z4kjzXq?K;2hKIMqW0mljHB*Zo-Hx8EM9*3u)SB4d!`r>5D!r$yYqieR*s<-{L?t$1 zWoq%U?f7IRK52beizK%rCo7SY*45gZIXv$hdidMz(eoAf_no(9UyCl!=(hxn6aBc9 zmgvX5#In29CHkqSB~|r;BKUw28_A=eN?oE^>JrUTmuQx{M6=W-nx!t$EOm)ysY^6V zU7}g)9L=!a4za96fyWf1ttc_zG2v({N?h|m%Xk|N&{l+UQTv;X+b*}EYO2&4DIdju|f=MqrQydrS1NBl2E%Fb>8 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/layout.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/layout.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8bb0d7c3dc20f0a20134c47cfe3529631a27cfe6 GIT binary patch literal 2372 zcmZuyO>7fK6rNe{uGjWDA$CF%{sIIQmX^@+TNS8^D50tns}iAym8I3<8Io;x*Y4~l zv5^l}#Q}*{;s(c@szh+;vB%!IaB!utC#s&frAiQ0FYSA~w#kpj_BZpr_jYFI{rN>c zpCvHtU+ygYlP2UZB;BEO7Mmd~o)AVDb%{q!N^vc@l9w`5o@~mVVk(|$s>YI7}s$DoouWRr^ZQ zAl2Az+e}|+7Nj|rW*W;p&-T2g_mzS#!8W(cb^xSn=0bcOv`|+=Jipgq1@KS z*GCRKlz+7W(Qb`nH6$6k`$r!^I@okS=R+P0YugVr(T^aA$rY6c}TH!4#*^1Wx5H z_qZPhmL*PuXpM*uQEedPyHJ2d&<1!wUJo2<-TJe5boJz~mtPuJ+Qn6I(6Ug4wrcNczx2uxXV8Nf)1leoq$;=l&D4OCYWMvUwI z!Q|LpzE6WN&;cOdwK(7Z(8gm|7!u@ZPJ9G9aRy-u;VeR&K5ptGL`-&09*Pg XT6}zUi@>z?EzMKoVfihADR#{N-~BfP literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/legend.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/legend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a193ef5e9e7e96eeb186ab779407436283358c48 GIT binary patch literal 2432 zcmb7F&2Jl35Pxg0*Xxh9Q^&C#Cu#Zt1xslHr9~=~@{u&5BC;ZqN@y`!ZM~0VVb^xw zZh~Fq;6o3QTBJ${wGx+#10re8(gt*treDEn*Q%a)>MGl7w=|3AtfC?8>_AM)ZiQ z=!&q1ov5qos*q(T=En87o6r+(Qcr>{VkwU1ru3AMqfXi#&n1%n>Vg zjaYFi-3@?KbMnr>wF@ zYipHx`*OvzeR{HCR=+lvsaJtI)f%m)GgVzNnLiceW3tiWs$tkQ+c%7>*%vZ4*|Q#n zNIZI%cqBU6!iM~9YzH<;NoM$&v*mIrjYrl@ml_6-8-`oARvna+ zhH+)pbh0Zr?<2Z+Ov-b zC))E*6_U$$3S*sIu~Qh`jj560;0<{A!JYjl?7ZCB%P=&4l%RjR-4JxRCHM7ikKc>* zE!g1+nzWRA(SFx!U`v5T?R%w#*T6onLts;^Sl=fjd?=vKPa{GMpRzffI z_|#=p%F=*U!>uHgRtb89D?tN6A4`{c$Y)$~xCDsfL0L1MRqF9r;ImMN;lQ$xqa`*7 z2+9yVfB=mJCJMZ%us6WMGH6yDF=lwQzD60y>`mOlJ}6hQ5qhi7!q33+e^|IK11GzK zmXP%bXuTOl))mnDTyGIJ0*A9x040@;qTCOZy@l#&gnopgNj;2GkQX56OKjAu=^%A| zX1xbSZwdgIl_ACBK&ez`Dy4L^_%F26kW_ejc9 zKFqGY`(Tf>>{UDhQy`)h;Rk7X9c>5`@b7&OfOO3PT?dALJ$7zu;C%byb~=0W^WV}( z+aGUdia(ERWzMueLC)rYzuH;ga;k7=W-C={&jG6+j-PtqZzX1c*2VEV$`2-WeMQ%6EnZ_XGN;Q$6})oaNFGKiZq5lNR-=%x?H~=1szc z?q9|Xn~P@;@(c2e4aTq@q6)ltkmn?AR;eSh$VU!zsENCqiBgF&i%BZVhlS*dw_-M^ z$FPEMjX`ySYT+CcS^rNtxOy&_)#us!;DS@jn+13pmL%z!LZo+}haysFhX6cF66wtI okSvA%A^@n4JR+|>BE?;0P#V5Du}k2wJ25T|Z&aQUc!;w93#Vy5F8}}l literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/line_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/line_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f50f5ef1a9032c0aed9c88e259ddb1a927ce2122 GIT binary patch literal 4555 zcmd6q-ER}w6~OQKV>}*v?AT76#18q`<;yGt3T)e@+bxg~Ac~?&2@gApG#Wg2iDAYz zcP5Y^9{hk*R@zobs9GMQs#-OIhrX5np{s3OT*X|03Tj{W4FoGzed;-PY~y5&Xm?+F zA?KcZ?uYN3bMJ4?{8`gf0>%8|+;SyJ$Um{sF5#B);ww--Cl;|Jn>dm#IRQQ31ofbV zwtyXS!g^TfL0fhrdc;w51==AiY)2hcSA{OyF(BPI^415gf$7) zzAkHiEmcT=jS~w&9$s9lQj04K^zsTV7by>)uuG;}khpeg)uUy%R4LDuT(1z|(Ru26 z)LNh(SAF$lrDA_A;X)FRPA!|vJ88NU8tS>~bmeOKq{(olq(Az!Sv}!YR?1!>%#}sD z>YZ3ExjZ(%;!sv9iiWxXDs_EbEI3yxQC>-$0CCzLKU!u?*>|O=pHqDYd^AciAa?6-LE25_?MNdab`=6!WB%erD^hQ+A+$5`#-oHQ!F`h8+d0%@n z$P-n{inQ!4cxLeu2Fmr!vSl)hM?gapctpNp+AGvu+yKv;wq3bulq+Sr5#SnKt0^mj_+S*eDK; zPJTT^AW|iAUH-lF8%ZK-WFs)YK?)Hz4rAB^ig!@pPT9L4c-UQm2jz-kl*%Q~FbWC} zxzzsT%`*a*uEO~;ini&xhT$r(%D7)@|1M4)TRI1>aF-SRKR%xOQxMN?_m)b z?E4L!;=3Co#WE;_<1vgZjY5O~PX$-eCE|X%tPi_HVB!Y&5$?7)iTFd*rVboz@VW2+ z*IF?sQrk9+4T-%6b6q?`$Ju^dW}q!laq--JdxJbp4*hLnwvn8xoq3qbuX~Nu{@UzA zHNBqw<8(v)pf>d|o?6%L?`*_>Q9Jc8mA!TK_9zVK8(5#cf3(qeymt0UX1F%@Br{u^ zdnS|ouI9*ib6~JJm~ZCCUd6QV*mDAc9cce}5tL48pW7E_V4vNTu_Qf6Ll?!%r88P6 zdKm2Stu}1wGT0M6>=Ce|8@Cl*0XuqrThZH;3fv2J$c2m5!NCY{a9D6K2ONy@Xa|El zikC$YagmL{Y?cE7r(*|HfG>5qG*`JQ_{7zf&Rd7ej>#?o2xQl(RJ>&#GFQ)9y$N;) zR{9|X^P;eTD0f>m5Urg&5Kn6vNmno4EK$5vTNAw7xt(`x7xWiYb_^=^GZY`9_&Ew( zn9Hk%39m(lCx^>xeq#@IBUTCuE1=$EI+x)MJm-3B9}Wl>-oA+KN7;$n4l4iJ1}Jg0Hp25*3VAk(+c}5=4-k)d z<^{x&fBVPL-UItga7e&LJZcQb33mx{z4jTt!q`a^=y-M<1-g!%Kyd^GJ~KOt;(ZX^ z0Qw0UQ5?pOKY;)MJxL7LPCrTR*i7!OCwJG*G*e@nseSd-zS?Y49oke!>gq^ssu|C1 z#>eaN@!F{-j@?sF?x~%9n#!*0_oo}F6M&>{T^n3K+R*maW*&BF>Gd6eEbVx0=Bbum zA8u&xVSjo(-_Q=!W}ajwHZzm;%;aBxRH|o6f@V7=kY+<8{{L68B+?9oPcwXy-ZWeO zKciXu=IAjXO}q!k;(}zad50uRZDCvbI~L?voc3>F8O{?B=uRF~?f2h+kk?5MJ@}IHOII&mL{U7<9z^Nt?Yt8~4TKYh93>!BKeQ+oXKsdT+&Ke^(Scpu7xAyXQdopxm0i{dc^4lpViq z3xX=zXP53Att*APa_|o)A1DX?dyE_|jBNuan+EG!pov+C@4){ZpKo$6o5e-n0#f01 z6d%K%`xg)br1|d;(&Xra@S*1fgdZ4u!ui4o?{BC7lNNQ0tW@>j6U%>PiF8_I&ADEKCh01q!%T*S zc)sTV_&SEqJ3m#&E5>F2!-CfPudH4`#F=6T60v-U&j39py@f2@Dyd-|! zj;}}_w((0_QP0SRiI)Vb Sm-EtI>CmmoZwOT4Xa56S(%2mU literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/marker.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/marker.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37ccb88c587fc2816fc81ec4027faad4f2eea158 GIT binary patch literal 2751 zcmai0OKcQJ5bfEWot^#qv+FPaPY6S>`34do2?WRB$ZQ;8E~Ax3EoE>;c^1R`AxxFC$g-UxQTEf~-AlxJtu_TAMk}gRo$DEiO*W<3N%R-Mk30Kh-H>oFu zE<385(o=3)PrDgC<7V|N*b|oG*R2k};xplbxujU`^39*wl_^25ea?bq7xcL(d7H{05&cE3J2@ zNc3mrtn3X*@2O?9JXbE5>X>#?=tg;myKUX@Se;eCR_Gl&hvQPXnF|eIsO)KEew=Iu9_d#d+Md zJpc%C+H@TMGm)9wkUB^etw3&!5OT_PgFC#WI>lg*64cxo$e0}1*C=}(mP(a&d_jS7 zA_S{wZ5-exsY`WYfE0~-4766H2&u;#>9Di+PRr+dydDRyRwWWrBe$iJCbPY;&NKjC zILFNDoLw=UDdxlZLYoHSBw7NFMV-sfe1(}SbRnD!!T{g39ml`M*%ReU0cAmX+PAFH zi{od@XU(8uS`;4n3EVv>TV`k)wp;aCNLl$R^{$pD?U{05hjgTBR<4+{G$_OCy=ra2 zIZ&B1S$H7I;%K$TRl~47sCDC7SCrz>wqYL}BG?1aAdj)G&D3FkIi7cTmn622_I6T1kfHEQ%}xJ6RGz z#11-86hJ1Uv>yTU$1p6sF#D3AD!4p~%kT>7P?vgPU>NKmm~Inx2$v5a^t53!2muAS zK_2G&8|VJa4gW)=-5*O2cO6cHDc_GgkOx+By-Qo}A8qDNH^v_pMjDfk6*9DCxqle{2RE;$(utwy1o-j|e8>CY zSbG5QBH!DUrYC@_iWLLix7nKni%L^qlRFGgzu<+OmpAOoiha2a`|@DxvJ#zVcMG4M z4L-fXR@h)GT8iG+?iTIYN?9s&js99vOY_ti)aI0Ldm;3Nsc>481V`CxaNURqNglVY z1>S9YSAicBmrHck3~i8m!G)_c^E1%2kBspYHf0~1bi|Z=tHZQfX{nL||Muum`*X1T zAGLwPt!4^Dm!BteJpo!fMWn7k6TnIpqn(=TN?idjtUod8NzkyA#i$YX1_+wUPQk?9 zLBNZ#cM;x0cvjt~LDf=h1g)=h7d${uQSAZVS~LoTsKT-2ul05U-=Q=1(qIe#=v*Yl z0pPK^y#3&!+*F}hHw$(TZigwiJhT(0{EH+9;&0u*DF3c*67{U9NOm0B06Pp%W=9Z? zBD{%!r;Dzlq9m@5@r+pb%0M8^*)fDX!fAvK!P#+C@sjK34_r{vJw;SUtT|-OL&8~fo^DEt3ZWWu|qm7AIF}-j2 z*4AIfntc(k~BhUEZ_}8^HG6*aLcc6C=@4@qi_*pYLdQ zC}>!WeA7$4Jn_4RiR6e} ziO!2P&J{=eXkj@}*Z>0N0zRs9W)(iuatL24ASGiyGiFQ{WmIHfV^+9&D(e34vJc?_ z*uH{u0FUF6Bt21xbnl!g||>jb9t QW4ol0Z?jJbOd_WL0a84eGynhq literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/picture.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/picture.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e81491876bba32761ee14227beea3e18ed651c78 GIT binary patch literal 1295 zcmZux&2Jk;6rb5IJC1D#F@z>fNkWC#B3vqQfuaf#NTn(SHuCeDu*8VAGlP=NY0#!IB|>QR!E$9vuj7R%2@i%`@J_`@AuyNw??Ce zV341;cMmOu{?cSJ?6EPr0md<+h~gL}*uz-cMr#ncT6$Yv;KpTv7i@H(V*-&S>!=W%Zb;CwTvgA@rz^H)i-RXk?e#{sZ)VkGhM{dEr4TmfDcem1T-8N!0?0~ zn83ywL(Bp;E?@zrpbaCvnsKs)cLY7j&qK@fa9xA{zs+LOSm`b}>E^wDV(ExJe6pn73=@y&9c zzkFnU_rh@Til+0!rFV|3KdOr(SdLt~qleqnm!u?NL7-|ukYsc()^h zN1I%0_PjV1?JE@0pJySH-p*o{uvCg5;Pc?WkNAQPU(hf$0o^Qu034#n%}f28f6gx6 zYdxfc+3WrFlmFW@3qQ(-9}i~U>)$$QE&qOH{n2OMp!Iow<795-9{u&*!Q6+Btk&b% zJN@-j2fg?l1 zx$DX=q7o;2t1 NwIBSa2&UqM{{WsLR09A2 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/pie_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/pie_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a5f43acce980e28a6c7682334f2ea1ee5f1a83a GIT binary patch literal 6056 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/plotarea.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/plotarea.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdbef7fcb5e092486a72eaf2bbd8b8e8dd079368 GIT binary patch literal 6421 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/print_settings.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/print_settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b72ca0de246850cc3de7a747eecd99cfc2c21cc5 GIT binary patch literal 2129 zcma)7O>7fK6rR~%|K`Vm{1hTgQ=u*bBNZ-9t5OsQrA;j)K&@65tBq%pY*~BV*$rUi zgAX|%rIm8y%Bd1cRrScR_g-^IMydqrq2&fjP^F&w-mGn6DThwv@6G#}nVt9EeEGdt z%n=y=Pj}XSF$wt-mHq%-jr}zcPY5H7hNMAVN^!1*T0?jBhT$3w(>0Y%53Ppn+G=iu znMT&lQlgRTgqa(JS)6X`>6UIzS#7Xp4q5ZgjdRaN<%% zT#ZpzXPRqhgqz#Fc-I2WX8JZw4Q^)0n^j(8;D!4fTANp1bKorud5g+x4ZI^m-q9g# zjAfavS%Uh`{TtOm{a(cN4b#tp`sNl^F0auSuJ7H_uN55vlXNZgCpI8Q1q zSW&@cjdWRgc|9rfkT+mix#>4}T=oSovtVU~3$)Fjzo0gjd0g5%Owv$NA!#D%a^3Ew z2!#ee%TAA8 zF0`;Iy_hFS&|Hlxt+vc~UeF8@&wF(2P!%hE>nZ%Oa{yhkJ6?Kh{9qj|CQpJdzl-9> z{654J$jx6U3Hkf7m9^$;Tz#1w9H z906HJ0oF410XE1RO*1pEEi!ttd;MjmxM_ErU^FB26 zh^mpJSF2U0C@@x>M3_au7b1`qLmF$b9nHQE};OQ}DAQ jh5)=R5PIXM literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/radar_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/radar_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85772f31eaa28ba4cdfc94ffc24f91eaa2d9e2fc GIT binary patch literal 2032 zcmZuy&2JM&6rZ)d>-E~3#Q8A64h9M>H7!A^=z)Gvz!DMMTNTR*OkD*3UH~xuVrtoHKKF! z@8pbF_OGktHJBgcy-li1}pz-ntMlMu~!Q3A05i`cKS8T}I~sdaJ2PlMZIAb=7aSnu-vY zcG|Q7Wcm@1&WnJFG)Zlq32EvbD+Vutvtsf|6?2v_?^au^#f3}?%K4P?rf}yRX;`2R zhH8N<{5S7{_}RFFmW^fP529!}0al+RgqD+F_2~dB1y;Xg5sET{hgSOvLi8JylMiX5 zs|{(2MLJ z4_J!&T#JzD*)!F86^jNY^c&u~1nh`9fu8V#u-)Pj<@F`nT&mZC`ML-qdZ>*Xm+=A> z^;VlU+uaU3+)y2NSkvcgeY)M{AHbI1js0Iy(_80di~IF7 zR)EP~pD4oQJT8=PUjiljxUlzjs1@72k$z}TKD5hsKY3)AH(?o7E8{TD@b{FQsgx8} zO&n6+myYj;Ewadzp7Z@Hi^z9+IsssKZ2-peWh3h3Qaz!oQr-b5_Ls_T{pE4TKW(4$Ttfbqgt3eq9mJNOo z5``+-JdC)4i`ZvLm;q9%akDQyclx%8@@# zt>uq`*BME4?7Dws%{|^b^K`7(t33n9 zr;EyCw8pwD6LOUz0MAqyI&#@{Nuq1XDS7`cTgYG zgo*|a+7UGIv;t=E72vAtar2ODnEY zo>SYyT>>4aIf~mZrcP5XO{P8!G2a?~RbugLDoUjNMO<$FOr5~yt0t- r`Rhc=NW4TKUOCA4^er=ojPhUTz!Ow_g7*Al?KO7a+W88>q?i8>0tgAH literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/reader.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/reader.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c422dba7d7e792a5110aec30965dc4e249f50fb9 GIT binary patch literal 1795 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 Oaj(y~Ul6=9`}_yOPWF)i literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/scatter_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/scatter_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b550da9ec2e41a52ed731fcd9ad679de7c2c9685 GIT binary patch literal 2043 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 Gz<&TK9w(vz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/series_factory.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/series_factory.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bce19a50140044401e84d6e32eff7c53fbb1ab24 GIT binary patch literal 1748 zcmah}-D?|15a0XIojxroCUT;DRCW?4YKdLDG)1XhXdT=@Q&Z}sO%H*%NNfAtJDs|> zaxLWqHuOQEEe+%$dFVr-Cb(D+{y+L+_mQe3cBFs5bIzzapFzrPq3;CFZ(Sa^si%hOvnqCPKZr-!U4 zWwyQZ7Pr&0ZXjDEAJ}Mh@aCS~PVd_Yl=xM-Ck%YRD>xwbpdIjIHUt{+&uPp@w&2HZ z^-)78581+I^vK>8TB2_U_r!f~n)H#4S^?jpCHbf!+1%#l02kaVxZno3;OMY_d%t$s zmTbA;bs#&VBfiBzCfv(10k5cUYxA4e2Xf+HkrO|V6aUiM`J;$_o-Omovo`mC#HH zCL&{bT|VLY!3adX?k!l9fL&d_`(|VG?o-nIM6K_*iNLMBu4iWqd$#58Jpf8o8G;4kjOOyoy4iFE87=-o^=va z_X6$E&|WAFx<}YaoNor6#nM~j+gF^iX(#s9#(Y~I+LP0r_{m2Xw{lMWawqlL_UBIO z?dFG_+d?L8K!7Qj_pOxc81S9THdNT!&9B~x!n;b zox3l0(idA2;7hrK^wsA4_a8k=jyyO4Hyu9(j^W?s=$?F{J;JVywj;@nj}M__lob~i z7Ur{YH{$WzeWQWa@cJP{{J&+dx5zng^cutKoTHXhXAHAc)$x1e4G`HMs&y8&zXgut{*e$jyN_mmLz$;2cYtzF(aZ}e!yWVd{{t@t Boe2N{ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/shapes.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/shapes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..50cb68626b73677c89829cdee0d273bbc973bc22 GIT binary patch literal 2847 zcmZuzO>7&-6`m!RwU$CfPFt)d!{f&dG_ixp=mZnJ-# zSxREd0zCL&AT3~^hxi!eP@u32_*CTRdoBUO13gF&K~K5Kv5f$|q;G~?Dzv>M-oE#} zH$VI4dvEv4LLrObvj6d6^GDGBD~$L`4V7nIP(DQ%VZ}wBVk(Nz6K=vwnn_PJRcR;P zl$SQsQdixKr ztP|xyaf~PjxA;CO#)pcwJe(ky!M(quI8}#YL zzzyhPGjQr;iLg3#!YH8NP<{@gxa#=i77ao|BZshRif7iFc1SKPfl?>FP;wj8_E{sK z-uWe7UTm=_@K#9Rk%+bha*Gm1q64Hp*z!QCL*v;8ipU^Arh<`~z>1l~2~$lVlG;W% z`ML5?eE<>SGSh%&h=x-S(+?6uOb0BBGozTCjLDD16eLz0!%Bda$;3l#G;$J7v2xHZ!88!!BoK>;|X?afwI#$Y3F*Qz&b##LBNJVX3sFuuhIHXPr;PNPBOV}!0$x<)wFQw?)_nly8CTL9*eYtqAIvXKmLFb}c{f30Fm$AX@irkFXH-$P=zF zHh2M7b!q^OxfW-br~P2rab2#nz;&=xHQ3-#3n7I9qbJ0u% zXa5HADe5R4WW_$zNq{x1RD?Q7u!c1XmI~IeV}X?dE3SXkNrM&lQ`E_Hv(aeHxElYG z>0}@(6ED`$!O})n7A$>aX<*6DEs#zQtX%ACLz7&q=6QO+9hoM23cU19Ax;bNGaEpT=>}D zCTtUWw;#6m+_SP0&oa@zSuJdH&9WTdi7e|+3&6^kTSP7P{u*}1ZiDEe{RK38Om^vms~_E5Td~&G2WKjHCmF(LAYs^n_9p7( zpsh;g@abDnNQC+?`CcNF>cX3q3Q7)mA*d=D1(i2^!_NG^(SWz|RT^F2i-^yhz+ZJ( zL~CMqkb_~vVwOeU0qCEIo)eRt6`~xASy0&bAnu^2s+Q9BE2uQxUHP_9`5q}pZ!6DH zvN+XUews!3iTi(k6!miNb(fx$r|&iXUg+L@QmTA)^1@@aSGwN4F=jkXqvFhG*8=2HfA`TZdbxKcesB2`55U6YSH~|tUg{NYc9-{6rSf)nbzejCNBT2|`g05Y z!^irEj*5R}t`Fcqm#*jYhf?!{bcjr>Rj2szxDaZ1^qIqIP++4kB`R7Iue>gfN)k!x z9Dbd@<`V`Dno8o#9z;-k7v71ry7*k zNrp=@OCC!C{02rJkb-OP4NB-&^aeOYlV%q|>?ajPd67oSl^+sGCGkQ_fB^IIH|XSl a&^tdQ(qJPH&nK@b%KZH^FOay)iT@A0x&Q?L literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/stock_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/stock_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0fd6ed7c130f2aa6fc2892b4ea457f855bf68db9 GIT binary patch literal 1975 zcmZ`(&uOtSqfIo&gqiy=G=j zoGJ$&kP1~>At6MMIaEkh_yhPKdP2=18G(RSJ#Yi12-H*G8`}^hI=0_@@6Frs?EAhq zzq_tOU<7y0UYIip`3s%i$acZb4*+fxN~ji*So1Uuu^#Dh#>>QpXT(`At74hRjB{QN zutBqt72BSzuo*dV-pj`YuMoSQt75sRFYfpH6}F;*xabuXwxhv#$Q#m#PEHZ(TqQKm z?2Sz4EZ*>Hq3k|Ir>x1sBI98Yg(6svSUDrJOREh=rM1W|H(9;LWcGLz1_CnOldY81 zMVQnpp-7)~a93D1@jy(}I*098qwDPa3E+FEBO{(hiKkP|%jkp|EPGeqz!SmnOo-%| zMKgDe4ZRz)A?DER>zusGDZG{Az9ZJBV*PLB4X9Z0t=OQ74edI`u!@ZAii}dz8>2aI z+$L{6)V@Z}Y1F!EdlT14OY=&Lr0hs%F->ZhRNbT_USp(zwHmCJGU}(m)KXdJL-3B$ z38E-j@#{$)D5I6-NJt}sikD595sdQ@OtL9Y8j1($TnH=4N*6a@Ga`+kb(+?4ow6y5 z63)YK=MI=#+HJC?tr1@>p;^y{q840zq5gJ*!(l^u9l@Oo5|6!%nPqdUVYv`=TG z{XMj6)#}Akd}TGRTWjQ}Lj>9?Bx|`}wV$D}R!Lc3_>GkFd<=5boAYr*6KG0kuwkXy z@&nK+$Ad_7RXH*%nhnOK<@;ehOntv>OGB{e-2d(+P0)Nrq*A}MB5mKVMS&2$FKpO# zUw5?srL$jD&jJskx|C2lvp7Fnoee}SpzK?oTm(Kvl|m!?QSqf<98f}ejdy8mXZfaPA#-M7Z?TT{P${D(EQ z1G|y3$@jvvfTKK#RjUUv^L^>~ew@%|gt*}QmzzPx2hbp^d`cRJo+v zrL4xH22S(P<-1}s6;8^=K1lPTLbDPEE5Z{g6!S%h6;~s0zKLI?x>3-Cn z-v%_f=^k#+KOUNBSDqQ#@E({fGCICBHn}x9y|rf_e#iH`bO*B2&j}d*Vegy^kw{H{E%xKR8k8cOdHEuY>vQBzW+S}x730$EaMV$QsyC{t^G3*lw7%-7>1+NuxJZup49v5P zrfDxsqJ8;NH#Ge@0rSEk+NXb$y^qMz`{d|Da^NA^_mGtSF%N3fHzr;XnAFDq0kDhk AvH$=8 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/surface_chart.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/surface_chart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1df56172ee8d875a1d15366c89fddaa27f71fef0 GIT binary patch literal 4439 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 bk@e~hg6W$HoWT7%r6ksGlP3r!ank<)*%z>| literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/trendline.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/trendline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2b7d099147ba029c8c5decf4acedaa1a8f7e1c6 GIT binary patch literal 3135 zcmb_eO^h2w7OuA2ZMWNPJ7drIXJ#@XK$1?#p#5QY0|5a^W(XRrh%uLzcdZ_GG1I%< zZl}6uGDf47SIQxWMMC0`NJwbJVMP=Ud*sN08yAF(WS4|swc@}nXc8fD;=O9yGu~tm zD{Uq7)qAgAx2xW(_r3l?*V6=s^^doCp&DSHVsA#8D1@segz$g-RAR8#fRX4=zC&C8e>uqSNA)xE5l6>`$ed3iH0{u{>K46Ob5 zWY9+U473DjG{T6 z0cAm>?%VeA`pTuoB`auIHic{QX9z*iu&vN)I$ppt7svRL@+B%aHiE>AU^PTL8a&38)EabF%UoPr$%rvZB8ex8&TZ^?hx z1~WyNl7qPgp%u$8sRNweRS&?G7)nhHV-A0zZF#iW zM3G_a*f9hVsXR&|Tslf3W?7U(;1rN}Ve`@2VL9}{Ec0v#fjz7$hVf-j;0o-3y40iX zFlaW}lVG|_*i*QC5}`1L5(vTH0B(}+vJ1V{f9W&(bN{^D*Dv%|hHCas{bReY{-*cp z@TgtOf4TJQPs6@;xp#S3UD{VZIRB+w8fy7FyYQ%X0j#stJHLDXkG&c`xA^IA`})hh zmG25K_SWtzq_POX9F!LZb5;CbUU;Bq5|wCoxUt6*z$v(+j}m|=z0vJ86Htx{#qyUY zlz`>0+J_~JrLS!gTlq-(BsnSMsQ8ge#_z)N*Qef|1519&g5^JLnR&!g084S|so6&? zz~Hd&($v1o!d98GRqd2He@HCTlC42!kj#ayYGk-Nx$az@R7Bm780MSJBH$%66dnh@ z0WJYTvKWuM{w7yFe+Rn4D?6K9?)Yw(Cp!KO%8;OUEO#5oJ1rjO`r(_AsuDi4p)V*v z@s4lvGVKJMhHlS36q&m<$Sc`T-p0b^w^XB?>@JH#&bykG^)LK{x<1wMF55e;P zqOCmzNNn8B$zBpPtTZw9QlL$Ub58{=HCao8rcN{sH1WBBmM&pSFc}(`MV*WK{XJON z9}q4eJdf}K!bOA^5ne*Ta~nE4f%3};|MSzL;scD_h+Cs6s&p*%n83jQ;+n6e}B z6;y{oK4eFB4poc{dj{c<7ne~*cn0KS>a5Z-pYu(EDo-`_&C3)hl!Ml2338W(=y#{QCGy9 z&p+0oEj}xmNR>#bNF=72YohB1{x%Q=!%NMTV9V;zfZ@%6&mU-cQ419PQ*=_%Q$?ah z0;iM8Qx~Jg{1ST&-hc!jTm`rvmn7+-LZladipf&!M*{FLO{C|3iY27j0RecJCDMs+ g$mwqhVD*7AFIC=aJRmSVxOiSN-pf2BFp2Q~0_LOS%m4rY literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/__pycache__/updown_bars.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chart/__pycache__/updown_bars.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96aa5465ddf89999acadba3893b32558c86c95b6 GIT binary patch literal 1225 zcmZuwOKTiQ5bmDW&OXK)Tec!AiY7Z zqrb2Be=-sJM>|uqC*))U$PQwN;Rwap$5?YCGGfy=3vNbMZ2LBFi`kJASNuxBoyd)= zezoA0s211#Iz|RsMaXzkBuNwg%*@?Qn*9(m z)z>GAlP;TlqZ>>Ir*EjQsYO0%1MHwJyoCs`(zXonw2Fmoncz*@LTCh&=!zypT6S(p z9^Dh~fg{dpI0ukBe5g87NnLJH+kb5Nc5hvBA$w~nW9_>u%e`eP1Ijo|<~}qddyFbd z!Z=HX;-dGECl7m_aHA(f#Xrty@PKY|*@G!2*=QKu2=oYV3^Lst(ZaN|QSK5FCZQta z@yuK0+SASV;WqLjz!)7j(8Z-E*3aI->;f$HgSo{g)-T=(1X0U6`VE$Dx7#|SznIXN z6Oz{miBmR+G;a{{b$p+1EM5cwUzHhOVpcD(v`^U`0<#qqb#y>n0J_pE*I)A7pl=J}_$_pa`C&Id;$omk#C@4(2t!th)A6Sx1-Xw!D04s%M*V8Hg}bDJThZdh;g} z`ibP{Ps5Z(M2T{}bzhv@oCX9h3*y6_6YQheq$$cR5D literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chart/_chart.py b/venv/Lib/site-packages/openpyxl/chart/_chart.py new file mode 100644 index 0000000..6a61354 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/_chart.py @@ -0,0 +1,199 @@ +# Copyright (c) 2010-2024 openpyxl + +from collections import OrderedDict +from operator import attrgetter + +from openpyxl.descriptors import ( + Typed, + Integer, + Alias, + MinMax, + Bool, + Set, +) +from openpyxl.descriptors.sequence import ValueSequence +from openpyxl.descriptors.serialisable import Serialisable + +from ._3d import _3DBase +from .data_source import AxDataSource, NumRef +from .layout import Layout +from .legend import Legend +from .reference import Reference +from .series_factory import SeriesFactory +from .series import attribute_mapping +from .shapes import GraphicalProperties +from .title import TitleDescriptor + +class AxId(Serialisable): + + val = Integer() + + def __init__(self, val): + self.val = val + + +def PlotArea(): + from .chartspace import PlotArea + return PlotArea() + + +class ChartBase(Serialisable): + + """ + Base class for all charts + """ + + legend = Typed(expected_type=Legend, allow_none=True) + layout = Typed(expected_type=Layout, allow_none=True) + roundedCorners = Bool(allow_none=True) + axId = ValueSequence(expected_type=int) + visible_cells_only = Bool(allow_none=True) + display_blanks = Set(values=['span', 'gap', 'zero']) + graphical_properties = Typed(expected_type=GraphicalProperties, allow_none=True) + + _series_type = "" + ser = () + series = Alias('ser') + title = TitleDescriptor() + anchor = "E15" # default anchor position + width = 15 # in cm, approx 5 rows + height = 7.5 # in cm, approx 14 rows + _id = 1 + _path = "/xl/charts/chart{0}.xml" + style = MinMax(allow_none=True, min=1, max=48) + mime_type = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" + graphical_properties = Typed(expected_type=GraphicalProperties, allow_none=True) # mapped to chartspace + + __elements__ = () + + + def __init__(self, axId=(), **kw): + self._charts = [self] + self.title = None + self.layout = None + self.roundedCorners = None + self.legend = Legend() + self.graphical_properties = None + self.style = None + self.plot_area = PlotArea() + self.axId = axId + self.display_blanks = 'gap' + self.pivotSource = None + self.pivotFormats = () + self.visible_cells_only = True + self.idx_base = 0 + self.graphical_properties = None + super().__init__() + + + def __hash__(self): + """ + Just need to check for identity + """ + return id(self) + + def __iadd__(self, other): + """ + Combine the chart with another one + """ + if not isinstance(other, ChartBase): + raise TypeError("Only other charts can be added") + self._charts.append(other) + return self + + + def to_tree(self, namespace=None, tagname=None, idx=None): + self.axId = [id for id in self._axes] + if self.ser is not None: + for s in self.ser: + s.__elements__ = attribute_mapping[self._series_type] + return super().to_tree(tagname, idx) + + + def _reindex(self): + """ + Normalise and rebase series: sort by order and then rebase order + + """ + # sort data series in order and rebase + ds = sorted(self.series, key=attrgetter("order")) + for idx, s in enumerate(ds): + s.order = idx + self.series = ds + + + def _write(self): + from .chartspace import ChartSpace, ChartContainer + self.plot_area.layout = self.layout + + idx_base = self.idx_base + for chart in self._charts: + if chart not in self.plot_area._charts: + chart.idx_base = idx_base + idx_base += len(chart.series) + self.plot_area._charts = self._charts + + container = ChartContainer(plotArea=self.plot_area, legend=self.legend, title=self.title) + if isinstance(chart, _3DBase): + container.view3D = chart.view3D + container.floor = chart.floor + container.sideWall = chart.sideWall + container.backWall = chart.backWall + container.plotVisOnly = self.visible_cells_only + container.dispBlanksAs = self.display_blanks + container.pivotFmts = self.pivotFormats + cs = ChartSpace(chart=container) + cs.style = self.style + cs.roundedCorners = self.roundedCorners + cs.pivotSource = self.pivotSource + cs.spPr = self.graphical_properties + return cs.to_tree() + + + @property + def _axes(self): + x = getattr(self, "x_axis", None) + y = getattr(self, "y_axis", None) + z = getattr(self, "z_axis", None) + return OrderedDict([(axis.axId, axis) for axis in (x, y, z) if axis]) + + + def set_categories(self, labels): + """ + Set the categories / x-axis values + """ + if not isinstance(labels, Reference): + labels = Reference(range_string=labels) + for s in self.ser: + s.cat = AxDataSource(numRef=NumRef(f=labels)) + + + def add_data(self, data, from_rows=False, titles_from_data=False): + """ + Add a range of data in a single pass. + The default is to treat each column as a data series. + """ + if not isinstance(data, Reference): + data = Reference(range_string=data) + + if from_rows: + values = data.rows + + else: + values = data.cols + + for ref in values: + series = SeriesFactory(ref, title_from_data=titles_from_data) + self.series.append(series) + + + def append(self, value): + """Append a data series to the chart""" + l = self.series[:] + l.append(value) + self.series = l + + + @property + def path(self): + return self._path.format(self._id) diff --git a/venv/Lib/site-packages/openpyxl/chart/area_chart.py b/venv/Lib/site-packages/openpyxl/chart/area_chart.py new file mode 100644 index 0000000..d3d9808 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/area_chart.py @@ -0,0 +1,106 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Set, + Bool, + Integer, + Sequence, + Alias, +) + +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedMinMax, + NestedSet, + NestedBool, +) + +from ._chart import ChartBase +from .descriptors import NestedGapAmount +from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines +from .label import DataLabelList +from .series import Series + + +class _AreaChartBase(ChartBase): + + grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked'])) + varyColors = NestedBool(nested=True, allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + dropLines = Typed(expected_type=ChartLines, allow_none=True) + + _series_type = "area" + + __elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines') + + def __init__(self, + grouping="standard", + varyColors=None, + ser=(), + dLbls=None, + dropLines=None, + ): + self.grouping = grouping + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + self.dropLines = dropLines + super().__init__() + + +class AreaChart(_AreaChartBase): + + tagname = "areaChart" + + grouping = _AreaChartBase.grouping + varyColors = _AreaChartBase.varyColors + ser = _AreaChartBase.ser + dLbls = _AreaChartBase.dLbls + dropLines = _AreaChartBase.dropLines + + # chart properties actually used by containing classes + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _AreaChartBase.__elements__ + ('axId',) + + def __init__(self, + axId=None, + extLst=None, + **kw + ): + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + super().__init__(**kw) + + +class AreaChart3D(AreaChart): + + tagname = "area3DChart" + + grouping = _AreaChartBase.grouping + varyColors = _AreaChartBase.varyColors + ser = _AreaChartBase.ser + dLbls = _AreaChartBase.dLbls + dropLines = _AreaChartBase.dropLines + + gapDepth = NestedGapAmount() + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + z_axis = Typed(expected_type=SeriesAxis, allow_none=True) + + __elements__ = AreaChart.__elements__ + ('gapDepth', ) + + def __init__(self, gapDepth=None, **kw): + self.gapDepth = gapDepth + super(AreaChart3D, self).__init__(**kw) + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + self.z_axis = SeriesAxis() diff --git a/venv/Lib/site-packages/openpyxl/chart/axis.py b/venv/Lib/site-packages/openpyxl/chart/axis.py new file mode 100644 index 0000000..7e99416 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/axis.py @@ -0,0 +1,401 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Float, + NoneSet, + Bool, + Integer, + MinMax, + NoneSet, + Set, + String, + Alias, +) + +from openpyxl.descriptors.excel import ( + ExtensionList, + Percentage, + _explicit_none, +) +from openpyxl.descriptors.nested import ( + NestedValue, + NestedSet, + NestedBool, + NestedNoneSet, + NestedFloat, + NestedInteger, + NestedMinMax, +) +from openpyxl.xml.constants import CHART_NS + +from .descriptors import NumberFormatDescriptor +from .layout import Layout +from .text import Text, RichText +from .shapes import GraphicalProperties +from .title import Title, TitleDescriptor + + +class ChartLines(Serialisable): + + tagname = "chartLines" + + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + + def __init__(self, spPr=None): + self.spPr = spPr + + +class Scaling(Serialisable): + + tagname = "scaling" + + logBase = NestedFloat(allow_none=True) + orientation = NestedSet(values=(['maxMin', 'minMax'])) + max = NestedFloat(allow_none=True) + min = NestedFloat(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('logBase', 'orientation', 'max', 'min',) + + def __init__(self, + logBase=None, + orientation="minMax", + max=None, + min=None, + extLst=None, + ): + self.logBase = logBase + self.orientation = orientation + self.max = max + self.min = min + + +class _BaseAxis(Serialisable): + + axId = NestedInteger(expected_type=int) + scaling = Typed(expected_type=Scaling) + delete = NestedBool(allow_none=True) + axPos = NestedSet(values=(['b', 'l', 'r', 't'])) + majorGridlines = Typed(expected_type=ChartLines, allow_none=True) + minorGridlines = Typed(expected_type=ChartLines, allow_none=True) + title = TitleDescriptor() + numFmt = NumberFormatDescriptor() + number_format = Alias("numFmt") + majorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none) + minorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none) + tickLblPos = NestedNoneSet(values=(['high', 'low', 'nextTo'])) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + txPr = Typed(expected_type=RichText, allow_none=True) + textProperties = Alias('txPr') + crossAx = NestedInteger(expected_type=int) # references other axis + crosses = NestedNoneSet(values=(['autoZero', 'max', 'min'])) + crossesAt = NestedFloat(allow_none=True) + + # crosses & crossesAt are mutually exclusive + + __elements__ = ('axId', 'scaling', 'delete', 'axPos', 'majorGridlines', + 'minorGridlines', 'title', 'numFmt', 'majorTickMark', 'minorTickMark', + 'tickLblPos', 'spPr', 'txPr', 'crossAx', 'crosses', 'crossesAt') + + def __init__(self, + axId=None, + scaling=None, + delete=None, + axPos='l', + majorGridlines=None, + minorGridlines=None, + title=None, + numFmt=None, + majorTickMark=None, + minorTickMark=None, + tickLblPos=None, + spPr=None, + txPr= None, + crossAx=None, + crosses=None, + crossesAt=None, + ): + self.axId = axId + if scaling is None: + scaling = Scaling() + self.scaling = scaling + self.delete = delete + self.axPos = axPos + self.majorGridlines = majorGridlines + self.minorGridlines = minorGridlines + self.title = title + self.numFmt = numFmt + self.majorTickMark = majorTickMark + self.minorTickMark = minorTickMark + self.tickLblPos = tickLblPos + self.spPr = spPr + self.txPr = txPr + self.crossAx = crossAx + self.crosses = crosses + self.crossesAt = crossesAt + + +class DisplayUnitsLabel(Serialisable): + + tagname = "dispUnitsLbl" + + layout = Typed(expected_type=Layout, allow_none=True) + tx = Typed(expected_type=Text, allow_none=True) + text = Alias("tx") + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + txPr = Typed(expected_type=RichText, allow_none=True) + textPropertes = Alias("txPr") + + __elements__ = ('layout', 'tx', 'spPr', 'txPr') + + def __init__(self, + layout=None, + tx=None, + spPr=None, + txPr=None, + ): + self.layout = layout + self.tx = tx + self.spPr = spPr + self.txPr = txPr + + +class DisplayUnitsLabelList(Serialisable): + + tagname = "dispUnits" + + custUnit = NestedFloat(allow_none=True) + builtInUnit = NestedNoneSet(values=(['hundreds', 'thousands', + 'tenThousands', 'hundredThousands', 'millions', 'tenMillions', + 'hundredMillions', 'billions', 'trillions'])) + dispUnitsLbl = Typed(expected_type=DisplayUnitsLabel, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('custUnit', 'builtInUnit', 'dispUnitsLbl',) + + def __init__(self, + custUnit=None, + builtInUnit=None, + dispUnitsLbl=None, + extLst=None, + ): + self.custUnit = custUnit + self.builtInUnit = builtInUnit + self.dispUnitsLbl = dispUnitsLbl + + +class NumericAxis(_BaseAxis): + + tagname = "valAx" + + axId = _BaseAxis.axId + scaling = _BaseAxis.scaling + delete = _BaseAxis.delete + axPos = _BaseAxis.axPos + majorGridlines = _BaseAxis.majorGridlines + minorGridlines = _BaseAxis.minorGridlines + title = _BaseAxis.title + numFmt = _BaseAxis.numFmt + majorTickMark = _BaseAxis.majorTickMark + minorTickMark = _BaseAxis.minorTickMark + tickLblPos = _BaseAxis.tickLblPos + spPr = _BaseAxis.spPr + txPr = _BaseAxis.txPr + crossAx = _BaseAxis.crossAx + crosses = _BaseAxis.crosses + crossesAt = _BaseAxis.crossesAt + + crossBetween = NestedNoneSet(values=(['between', 'midCat'])) + majorUnit = NestedFloat(allow_none=True) + minorUnit = NestedFloat(allow_none=True) + dispUnits = Typed(expected_type=DisplayUnitsLabelList, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _BaseAxis.__elements__ + ('crossBetween', 'majorUnit', + 'minorUnit', 'dispUnits',) + + + def __init__(self, + crossBetween=None, + majorUnit=None, + minorUnit=None, + dispUnits=None, + extLst=None, + **kw + ): + self.crossBetween = crossBetween + self.majorUnit = majorUnit + self.minorUnit = minorUnit + self.dispUnits = dispUnits + kw.setdefault('majorGridlines', ChartLines()) + kw.setdefault('axId', 100) + kw.setdefault('crossAx', 10) + super().__init__(**kw) + + + @classmethod + def from_tree(cls, node): + """ + Special case value axes with no gridlines + """ + self = super().from_tree(node) + gridlines = node.find("{%s}majorGridlines" % CHART_NS) + if gridlines is None: + self.majorGridlines = None + return self + + + +class TextAxis(_BaseAxis): + + tagname = "catAx" + + axId = _BaseAxis.axId + scaling = _BaseAxis.scaling + delete = _BaseAxis.delete + axPos = _BaseAxis.axPos + majorGridlines = _BaseAxis.majorGridlines + minorGridlines = _BaseAxis.minorGridlines + title = _BaseAxis.title + numFmt = _BaseAxis.numFmt + majorTickMark = _BaseAxis.majorTickMark + minorTickMark = _BaseAxis.minorTickMark + tickLblPos = _BaseAxis.tickLblPos + spPr = _BaseAxis.spPr + txPr = _BaseAxis.txPr + crossAx = _BaseAxis.crossAx + crosses = _BaseAxis.crosses + crossesAt = _BaseAxis.crossesAt + + auto = NestedBool(allow_none=True) + lblAlgn = NestedNoneSet(values=(['ctr', 'l', 'r'])) + lblOffset = NestedMinMax(min=0, max=1000) + tickLblSkip = NestedInteger(allow_none=True) + tickMarkSkip = NestedInteger(allow_none=True) + noMultiLvlLbl = NestedBool(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _BaseAxis.__elements__ + ('auto', 'lblAlgn', 'lblOffset', + 'tickLblSkip', 'tickMarkSkip', 'noMultiLvlLbl') + + def __init__(self, + auto=None, + lblAlgn=None, + lblOffset=100, + tickLblSkip=None, + tickMarkSkip=None, + noMultiLvlLbl=None, + extLst=None, + **kw + ): + self.auto = auto + self.lblAlgn = lblAlgn + self.lblOffset = lblOffset + self.tickLblSkip = tickLblSkip + self.tickMarkSkip = tickMarkSkip + self.noMultiLvlLbl = noMultiLvlLbl + kw.setdefault('axId', 10) + kw.setdefault('crossAx', 100) + super().__init__(**kw) + + +class DateAxis(TextAxis): + + tagname = "dateAx" + + axId = _BaseAxis.axId + scaling = _BaseAxis.scaling + delete = _BaseAxis.delete + axPos = _BaseAxis.axPos + majorGridlines = _BaseAxis.majorGridlines + minorGridlines = _BaseAxis.minorGridlines + title = _BaseAxis.title + numFmt = _BaseAxis.numFmt + majorTickMark = _BaseAxis.majorTickMark + minorTickMark = _BaseAxis.minorTickMark + tickLblPos = _BaseAxis.tickLblPos + spPr = _BaseAxis.spPr + txPr = _BaseAxis.txPr + crossAx = _BaseAxis.crossAx + crosses = _BaseAxis.crosses + crossesAt = _BaseAxis.crossesAt + + auto = NestedBool(allow_none=True) + lblOffset = NestedInteger(allow_none=True) + baseTimeUnit = NestedNoneSet(values=(['days', 'months', 'years'])) + majorUnit = NestedFloat(allow_none=True) + majorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years'])) + minorUnit = NestedFloat(allow_none=True) + minorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years'])) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _BaseAxis.__elements__ + ('auto', 'lblOffset', + 'baseTimeUnit', 'majorUnit', 'majorTimeUnit', 'minorUnit', + 'minorTimeUnit') + + def __init__(self, + auto=None, + lblOffset=None, + baseTimeUnit=None, + majorUnit=None, + majorTimeUnit=None, + minorUnit=None, + minorTimeUnit=None, + extLst=None, + **kw + ): + self.auto = auto + self.lblOffset = lblOffset + self.baseTimeUnit = baseTimeUnit + self.majorUnit = majorUnit + self.majorTimeUnit = majorTimeUnit + self.minorUnit = minorUnit + self.minorTimeUnit = minorTimeUnit + kw.setdefault('axId', 500) + kw.setdefault('lblOffset', lblOffset) + super().__init__(**kw) + + +class SeriesAxis(_BaseAxis): + + tagname = "serAx" + + axId = _BaseAxis.axId + scaling = _BaseAxis.scaling + delete = _BaseAxis.delete + axPos = _BaseAxis.axPos + majorGridlines = _BaseAxis.majorGridlines + minorGridlines = _BaseAxis.minorGridlines + title = _BaseAxis.title + numFmt = _BaseAxis.numFmt + majorTickMark = _BaseAxis.majorTickMark + minorTickMark = _BaseAxis.minorTickMark + tickLblPos = _BaseAxis.tickLblPos + spPr = _BaseAxis.spPr + txPr = _BaseAxis.txPr + crossAx = _BaseAxis.crossAx + crosses = _BaseAxis.crosses + crossesAt = _BaseAxis.crossesAt + + tickLblSkip = NestedInteger(allow_none=True) + tickMarkSkip = NestedInteger(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _BaseAxis.__elements__ + ('tickLblSkip', 'tickMarkSkip') + + def __init__(self, + tickLblSkip=None, + tickMarkSkip=None, + extLst=None, + **kw + ): + self.tickLblSkip = tickLblSkip + self.tickMarkSkip = tickMarkSkip + kw.setdefault('axId', 1000) + kw.setdefault('crossAx', 10) + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/bar_chart.py b/venv/Lib/site-packages/openpyxl/chart/bar_chart.py new file mode 100644 index 0000000..fa08e07 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/bar_chart.py @@ -0,0 +1,144 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Bool, + Integer, + Sequence, + Alias, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedSet, + NestedBool, + NestedInteger, + NestedMinMax, +) + +from .descriptors import ( + NestedGapAmount, + NestedOverlap, +) +from ._chart import ChartBase +from ._3d import _3DBase +from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines +from .shapes import GraphicalProperties +from .series import Series +from .legend import Legend +from .label import DataLabelList + + +class _BarChartBase(ChartBase): + + barDir = NestedSet(values=(['bar', 'col'])) + type = Alias("barDir") + grouping = NestedSet(values=(['percentStacked', 'clustered', 'standard', + 'stacked'])) + varyColors = NestedBool(nested=True, allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + + __elements__ = ('barDir', 'grouping', 'varyColors', 'ser', 'dLbls') + + _series_type = "bar" + + def __init__(self, + barDir="col", + grouping="clustered", + varyColors=None, + ser=(), + dLbls=None, + **kw + ): + self.barDir = barDir + self.grouping = grouping + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + super().__init__(**kw) + + +class BarChart(_BarChartBase): + + tagname = "barChart" + + barDir = _BarChartBase.barDir + grouping = _BarChartBase.grouping + varyColors = _BarChartBase.varyColors + ser = _BarChartBase.ser + dLbls = _BarChartBase.dLbls + + gapWidth = NestedGapAmount() + overlap = NestedOverlap() + serLines = Typed(expected_type=ChartLines, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + # chart properties actually used by containing classes + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + + __elements__ = _BarChartBase.__elements__ + ('gapWidth', 'overlap', 'serLines', 'axId') + + def __init__(self, + gapWidth=150, + overlap=None, + serLines=None, + extLst=None, + **kw + ): + self.gapWidth = gapWidth + self.overlap = overlap + self.serLines = serLines + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + self.legend = Legend() + super().__init__(**kw) + + +class BarChart3D(_BarChartBase, _3DBase): + + tagname = "bar3DChart" + + barDir = _BarChartBase.barDir + grouping = _BarChartBase.grouping + varyColors = _BarChartBase.varyColors + ser = _BarChartBase.ser + dLbls = _BarChartBase.dLbls + + view3D = _3DBase.view3D + floor = _3DBase.floor + sideWall = _3DBase.sideWall + backWall = _3DBase.backWall + + gapWidth = NestedGapAmount() + gapDepth = NestedGapAmount() + shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax'])) + serLines = Typed(expected_type=ChartLines, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + z_axis = Typed(expected_type=SeriesAxis, allow_none=True) + + __elements__ = _BarChartBase.__elements__ + ('gapWidth', 'gapDepth', 'shape', 'serLines', 'axId') + + def __init__(self, + gapWidth=150, + gapDepth=150, + shape=None, + serLines=None, + extLst=None, + **kw + ): + self.gapWidth = gapWidth + self.gapDepth = gapDepth + self.shape = shape + self.serLines = serLines + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + self.z_axis = SeriesAxis() + + super(BarChart3D, self).__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/bubble_chart.py b/venv/Lib/site-packages/openpyxl/chart/bubble_chart.py new file mode 100644 index 0000000..3fca043 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/bubble_chart.py @@ -0,0 +1,67 @@ +#Autogenerated schema +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Set, + MinMax, + Bool, + Integer, + Alias, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedMinMax, + NestedBool, +) + +from ._chart import ChartBase +from .axis import TextAxis, NumericAxis +from .series import XYSeries +from .label import DataLabelList + + +class BubbleChart(ChartBase): + + tagname = "bubbleChart" + + varyColors = NestedBool(allow_none=True) + ser = Sequence(expected_type=XYSeries, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + bubble3D = NestedBool(allow_none=True) + bubbleScale = NestedMinMax(min=0, max=300, allow_none=True) + showNegBubbles = NestedBool(allow_none=True) + sizeRepresents = NestedNoneSet(values=(['area', 'w'])) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=NumericAxis) + y_axis = Typed(expected_type=NumericAxis) + + _series_type = "bubble" + + __elements__ = ('varyColors', 'ser', 'dLbls', 'bubble3D', 'bubbleScale', + 'showNegBubbles', 'sizeRepresents', 'axId') + + def __init__(self, + varyColors=None, + ser=(), + dLbls=None, + bubble3D=None, + bubbleScale=None, + showNegBubbles=None, + sizeRepresents=None, + extLst=None, + **kw + ): + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + self.bubble3D = bubble3D + self.bubbleScale = bubbleScale + self.showNegBubbles = showNegBubbles + self.sizeRepresents = sizeRepresents + self.x_axis = NumericAxis(axId=10, crossAx=20) + self.y_axis = NumericAxis(axId=20, crossAx=10) + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/chartspace.py b/venv/Lib/site-packages/openpyxl/chart/chartspace.py new file mode 100644 index 0000000..cba213c --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/chartspace.py @@ -0,0 +1,195 @@ + +# Copyright (c) 2010-2024 openpyxl + +""" +Enclosing chart object. The various chart types are actually child objects. +Will probably need to call this indirectly +""" + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + String, + Alias, +) +from openpyxl.descriptors.excel import ( + ExtensionList, + Relation +) +from openpyxl.descriptors.nested import ( + NestedBool, + NestedNoneSet, + NestedString, + NestedMinMax, +) +from openpyxl.descriptors.sequence import NestedSequence +from openpyxl.xml.constants import CHART_NS + +from openpyxl.drawing.colors import ColorMapping +from .text import RichText +from .shapes import GraphicalProperties +from .legend import Legend +from ._3d import _3DBase +from .plotarea import PlotArea +from .title import Title +from .pivot import ( + PivotFormat, + PivotSource, +) +from .print_settings import PrintSettings + + +class ChartContainer(Serialisable): + + tagname = "chart" + + title = Typed(expected_type=Title, allow_none=True) + autoTitleDeleted = NestedBool(allow_none=True) + pivotFmts = NestedSequence(expected_type=PivotFormat) + view3D = _3DBase.view3D + floor = _3DBase.floor + sideWall = _3DBase.sideWall + backWall = _3DBase.backWall + plotArea = Typed(expected_type=PlotArea, ) + legend = Typed(expected_type=Legend, allow_none=True) + plotVisOnly = NestedBool() + dispBlanksAs = NestedNoneSet(values=(['span', 'gap', 'zero'])) + showDLblsOverMax = NestedBool(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('title', 'autoTitleDeleted', 'pivotFmts', 'view3D', + 'floor', 'sideWall', 'backWall', 'plotArea', 'legend', 'plotVisOnly', + 'dispBlanksAs', 'showDLblsOverMax') + + def __init__(self, + title=None, + autoTitleDeleted=None, + pivotFmts=(), + view3D=None, + floor=None, + sideWall=None, + backWall=None, + plotArea=None, + legend=None, + plotVisOnly=True, + dispBlanksAs="gap", + showDLblsOverMax=None, + extLst=None, + ): + self.title = title + self.autoTitleDeleted = autoTitleDeleted + self.pivotFmts = pivotFmts + self.view3D = view3D + self.floor = floor + self.sideWall = sideWall + self.backWall = backWall + if plotArea is None: + plotArea = PlotArea() + self.plotArea = plotArea + self.legend = legend + self.plotVisOnly = plotVisOnly + self.dispBlanksAs = dispBlanksAs + self.showDLblsOverMax = showDLblsOverMax + + +class Protection(Serialisable): + + tagname = "protection" + + chartObject = NestedBool(allow_none=True) + data = NestedBool(allow_none=True) + formatting = NestedBool(allow_none=True) + selection = NestedBool(allow_none=True) + userInterface = NestedBool(allow_none=True) + + __elements__ = ("chartObject", "data", "formatting", "selection", "userInterface") + + def __init__(self, + chartObject=None, + data=None, + formatting=None, + selection=None, + userInterface=None, + ): + self.chartObject = chartObject + self.data = data + self.formatting = formatting + self.selection = selection + self.userInterface = userInterface + + +class ExternalData(Serialisable): + + tagname = "externalData" + + autoUpdate = NestedBool(allow_none=True) + id = String() # Needs namespace + + def __init__(self, + autoUpdate=None, + id=None + ): + self.autoUpdate = autoUpdate + self.id = id + + +class ChartSpace(Serialisable): + + tagname = "chartSpace" + + date1904 = NestedBool(allow_none=True) + lang = NestedString(allow_none=True) + roundedCorners = NestedBool(allow_none=True) + style = NestedMinMax(allow_none=True, min=1, max=48) + clrMapOvr = Typed(expected_type=ColorMapping, allow_none=True) + pivotSource = Typed(expected_type=PivotSource, allow_none=True) + protection = Typed(expected_type=Protection, allow_none=True) + chart = Typed(expected_type=ChartContainer) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphical_properties = Alias("spPr") + txPr = Typed(expected_type=RichText, allow_none=True) + textProperties = Alias("txPr") + externalData = Typed(expected_type=ExternalData, allow_none=True) + printSettings = Typed(expected_type=PrintSettings, allow_none=True) + userShapes = Relation() + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('date1904', 'lang', 'roundedCorners', 'style', + 'clrMapOvr', 'pivotSource', 'protection', 'chart', 'spPr', 'txPr', + 'externalData', 'printSettings', 'userShapes') + + def __init__(self, + date1904=None, + lang=None, + roundedCorners=None, + style=None, + clrMapOvr=None, + pivotSource=None, + protection=None, + chart=None, + spPr=None, + txPr=None, + externalData=None, + printSettings=None, + userShapes=None, + extLst=None, + ): + self.date1904 = date1904 + self.lang = lang + self.roundedCorners = roundedCorners + self.style = style + self.clrMapOvr = clrMapOvr + self.pivotSource = pivotSource + self.protection = protection + self.chart = chart + self.spPr = spPr + self.txPr = txPr + self.externalData = externalData + self.printSettings = printSettings + self.userShapes = userShapes + + + def to_tree(self, tagname=None, idx=None, namespace=None): + tree = super().to_tree() + tree.set("xmlns", CHART_NS) + return tree diff --git a/venv/Lib/site-packages/openpyxl/chart/data_source.py b/venv/Lib/site-packages/openpyxl/chart/data_source.py new file mode 100644 index 0000000..c38eafb --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/data_source.py @@ -0,0 +1,246 @@ +""" +Collection of utility primitives for charts. +""" + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Bool, + Typed, + Alias, + String, + Integer, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedString, + NestedText, + NestedInteger, +) + + +class NumFmt(Serialisable): + + formatCode = String() + sourceLinked = Bool() + + def __init__(self, + formatCode=None, + sourceLinked=False + ): + self.formatCode = formatCode + self.sourceLinked = sourceLinked + + +class NumberValueDescriptor(NestedText): + """ + Data should be numerical but isn't always :-/ + """ + + allow_none = True + + def __set__(self, instance, value): + if value == "#N/A": + self.expected_type = str + else: + self.expected_type = float + super().__set__(instance, value) + + +class NumVal(Serialisable): + + idx = Integer() + formatCode = NestedText(allow_none=True, expected_type=str) + v = NumberValueDescriptor() + + def __init__(self, + idx=None, + formatCode=None, + v=None, + ): + self.idx = idx + self.formatCode = formatCode + self.v = v + + +class NumData(Serialisable): + + formatCode = NestedText(expected_type=str, allow_none=True) + ptCount = NestedInteger(allow_none=True) + pt = Sequence(expected_type=NumVal) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('formatCode', 'ptCount', 'pt') + + def __init__(self, + formatCode=None, + ptCount=None, + pt=(), + extLst=None, + ): + self.formatCode = formatCode + self.ptCount = ptCount + self.pt = pt + + +class NumRef(Serialisable): + + f = NestedText(expected_type=str) + ref = Alias('f') + numCache = Typed(expected_type=NumData, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('f', 'numCache') + + def __init__(self, + f=None, + numCache=None, + extLst=None, + ): + self.f = f + self.numCache = numCache + + +class StrVal(Serialisable): + + tagname = "strVal" + + idx = Integer() + v = NestedText(expected_type=str) + + def __init__(self, + idx=0, + v=None, + ): + self.idx = idx + self.v = v + + +class StrData(Serialisable): + + tagname = "strData" + + ptCount = NestedInteger(allow_none=True) + pt = Sequence(expected_type=StrVal) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('ptCount', 'pt') + + def __init__(self, + ptCount=None, + pt=(), + extLst=None, + ): + self.ptCount = ptCount + self.pt = pt + + +class StrRef(Serialisable): + + tagname = "strRef" + + f = NestedText(expected_type=str, allow_none=True) + strCache = Typed(expected_type=StrData, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('f', 'strCache') + + def __init__(self, + f=None, + strCache=None, + extLst=None, + ): + self.f = f + self.strCache = strCache + + +class NumDataSource(Serialisable): + + numRef = Typed(expected_type=NumRef, allow_none=True) + numLit = Typed(expected_type=NumData, allow_none=True) + + + def __init__(self, + numRef=None, + numLit=None, + ): + self.numRef = numRef + self.numLit = numLit + + +class Level(Serialisable): + + tagname = "lvl" + + pt = Sequence(expected_type=StrVal) + + __elements__ = ('pt',) + + def __init__(self, + pt=(), + ): + self.pt = pt + + +class MultiLevelStrData(Serialisable): + + tagname = "multiLvlStrData" + + ptCount = Integer(allow_none=True) + lvl = Sequence(expected_type=Level) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('ptCount', 'lvl',) + + def __init__(self, + ptCount=None, + lvl=(), + extLst=None, + ): + self.ptCount = ptCount + self.lvl = lvl + + +class MultiLevelStrRef(Serialisable): + + tagname = "multiLvlStrRef" + + f = NestedText(expected_type=str) + multiLvlStrCache = Typed(expected_type=MultiLevelStrData, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('multiLvlStrCache', 'f') + + def __init__(self, + f=None, + multiLvlStrCache=None, + extLst=None, + ): + self.f = f + self.multiLvlStrCache = multiLvlStrCache + + +class AxDataSource(Serialisable): + + tagname = "cat" + + numRef = Typed(expected_type=NumRef, allow_none=True) + numLit = Typed(expected_type=NumData, allow_none=True) + strRef = Typed(expected_type=StrRef, allow_none=True) + strLit = Typed(expected_type=StrData, allow_none=True) + multiLvlStrRef = Typed(expected_type=MultiLevelStrRef, allow_none=True) + + def __init__(self, + numRef=None, + numLit=None, + strRef=None, + strLit=None, + multiLvlStrRef=None, + ): + if not any([numLit, numRef, strRef, strLit, multiLvlStrRef]): + raise TypeError("A data source must be provided") + self.numRef = numRef + self.numLit = numLit + self.strRef = strRef + self.strLit = strLit + self.multiLvlStrRef = multiLvlStrRef diff --git a/venv/Lib/site-packages/openpyxl/chart/descriptors.py b/venv/Lib/site-packages/openpyxl/chart/descriptors.py new file mode 100644 index 0000000..6bc9434 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/descriptors.py @@ -0,0 +1,43 @@ +# Copyright (c) 2010-2024 openpyxl + + + +from openpyxl.descriptors.nested import ( + NestedMinMax + ) + +from openpyxl.descriptors import Typed + +from .data_source import NumFmt + +""" +Utility descriptors for the chart module. +For convenience but also clarity. +""" + +class NestedGapAmount(NestedMinMax): + + allow_none = True + min = 0 + max = 500 + + +class NestedOverlap(NestedMinMax): + + allow_none = True + min = -100 + max = 100 + + +class NumberFormatDescriptor(Typed): + """ + Allow direct assignment of format code + """ + + expected_type = NumFmt + allow_none = True + + def __set__(self, instance, value): + if isinstance(value, str): + value = NumFmt(value) + super().__set__(instance, value) diff --git a/venv/Lib/site-packages/openpyxl/chart/error_bar.py b/venv/Lib/site-packages/openpyxl/chart/error_bar.py new file mode 100644 index 0000000..6ae2445 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/error_bar.py @@ -0,0 +1,62 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Float, + Set, + Alias +) + +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedSet, + NestedBool, + NestedFloat, +) + +from .data_source import NumDataSource +from .shapes import GraphicalProperties + + +class ErrorBars(Serialisable): + + tagname = "errBars" + + errDir = NestedNoneSet(values=(['x', 'y'])) + direction = Alias("errDir") + errBarType = NestedSet(values=(['both', 'minus', 'plus'])) + style = Alias("errBarType") + errValType = NestedSet(values=(['cust', 'fixedVal', 'percentage', 'stdDev', 'stdErr'])) + size = Alias("errValType") + noEndCap = NestedBool(nested=True, allow_none=True) + plus = Typed(expected_type=NumDataSource, allow_none=True) + minus = Typed(expected_type=NumDataSource, allow_none=True) + val = NestedFloat(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('errDir','errBarType', 'errValType', 'noEndCap','minus', 'plus', 'val', 'spPr') + + + def __init__(self, + errDir=None, + errBarType="both", + errValType="fixedVal", + noEndCap=None, + plus=None, + minus=None, + val=None, + spPr=None, + extLst=None, + ): + self.errDir = errDir + self.errBarType = errBarType + self.errValType = errValType + self.noEndCap = noEndCap + self.plus = plus + self.minus = minus + self.val = val + self.spPr = spPr diff --git a/venv/Lib/site-packages/openpyxl/chart/label.py b/venv/Lib/site-packages/openpyxl/chart/label.py new file mode 100644 index 0000000..d6eacb1 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/label.py @@ -0,0 +1,127 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Sequence, + Alias, + Typed +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedBool, + NestedString, + NestedInteger, + ) + +from .shapes import GraphicalProperties +from .text import RichText + + +class _DataLabelBase(Serialisable): + + numFmt = NestedString(allow_none=True, attribute="formatCode") + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + txPr = Typed(expected_type=RichText, allow_none=True) + textProperties = Alias('txPr') + dLblPos = NestedNoneSet(values=['bestFit', 'b', 'ctr', 'inBase', 'inEnd', + 'l', 'outEnd', 'r', 't']) + position = Alias('dLblPos') + showLegendKey = NestedBool(allow_none=True) + showVal = NestedBool(allow_none=True) + showCatName = NestedBool(allow_none=True) + showSerName = NestedBool(allow_none=True) + showPercent = NestedBool(allow_none=True) + showBubbleSize = NestedBool(allow_none=True) + showLeaderLines = NestedBool(allow_none=True) + separator = NestedString(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ("numFmt", "spPr", "txPr", "dLblPos", "showLegendKey", + "showVal", "showCatName", "showSerName", "showPercent", "showBubbleSize", + "showLeaderLines", "separator") + + def __init__(self, + numFmt=None, + spPr=None, + txPr=None, + dLblPos=None, + showLegendKey=None, + showVal=None, + showCatName=None, + showSerName=None, + showPercent=None, + showBubbleSize=None, + showLeaderLines=None, + separator=None, + extLst=None, + ): + self.numFmt = numFmt + self.spPr = spPr + self.txPr = txPr + self.dLblPos = dLblPos + self.showLegendKey = showLegendKey + self.showVal = showVal + self.showCatName = showCatName + self.showSerName = showSerName + self.showPercent = showPercent + self.showBubbleSize = showBubbleSize + self.showLeaderLines = showLeaderLines + self.separator = separator + + +class DataLabel(_DataLabelBase): + + tagname = "dLbl" + + idx = NestedInteger() + + numFmt = _DataLabelBase.numFmt + spPr = _DataLabelBase.spPr + txPr = _DataLabelBase.txPr + dLblPos = _DataLabelBase.dLblPos + showLegendKey = _DataLabelBase.showLegendKey + showVal = _DataLabelBase.showVal + showCatName = _DataLabelBase.showCatName + showSerName = _DataLabelBase.showSerName + showPercent = _DataLabelBase.showPercent + showBubbleSize = _DataLabelBase.showBubbleSize + showLeaderLines = _DataLabelBase.showLeaderLines + separator = _DataLabelBase.separator + extLst = _DataLabelBase.extLst + + __elements__ = ("idx",) + _DataLabelBase.__elements__ + + def __init__(self, idx=0, **kw ): + self.idx = idx + super().__init__(**kw) + + +class DataLabelList(_DataLabelBase): + + tagname = "dLbls" + + dLbl = Sequence(expected_type=DataLabel, allow_none=True) + + delete = NestedBool(allow_none=True) + numFmt = _DataLabelBase.numFmt + spPr = _DataLabelBase.spPr + txPr = _DataLabelBase.txPr + dLblPos = _DataLabelBase.dLblPos + showLegendKey = _DataLabelBase.showLegendKey + showVal = _DataLabelBase.showVal + showCatName = _DataLabelBase.showCatName + showSerName = _DataLabelBase.showSerName + showPercent = _DataLabelBase.showPercent + showBubbleSize = _DataLabelBase.showBubbleSize + showLeaderLines = _DataLabelBase.showLeaderLines + separator = _DataLabelBase.separator + extLst = _DataLabelBase.extLst + + __elements__ = ("delete", "dLbl",) + _DataLabelBase.__elements__ + + def __init__(self, dLbl=(), delete=None, **kw): + self.dLbl = dLbl + self.delete = delete + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/layout.py b/venv/Lib/site-packages/openpyxl/chart/layout.py new file mode 100644 index 0000000..f2f6553 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/layout.py @@ -0,0 +1,74 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + NoneSet, + Float, + Typed, + Alias, +) + +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedSet, + NestedMinMax, +) + +class ManualLayout(Serialisable): + + tagname = "manualLayout" + + layoutTarget = NestedNoneSet(values=(['inner', 'outer'])) + xMode = NestedNoneSet(values=(['edge', 'factor'])) + yMode = NestedNoneSet(values=(['edge', 'factor'])) + wMode = NestedSet(values=(['edge', 'factor'])) + hMode = NestedSet(values=(['edge', 'factor'])) + x = NestedMinMax(min=-1, max=1, allow_none=True) + y = NestedMinMax(min=-1, max=1, allow_none=True) + w = NestedMinMax(min=0, max=1, allow_none=True) + width = Alias('w') + h = NestedMinMax(min=0, max=1, allow_none=True) + height = Alias('h') + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('layoutTarget', 'xMode', 'yMode', 'wMode', 'hMode', 'x', + 'y', 'w', 'h') + + def __init__(self, + layoutTarget=None, + xMode=None, + yMode=None, + wMode="factor", + hMode="factor", + x=None, + y=None, + w=None, + h=None, + extLst=None, + ): + self.layoutTarget = layoutTarget + self.xMode = xMode + self.yMode = yMode + self.wMode = wMode + self.hMode = hMode + self.x = x + self.y = y + self.w = w + self.h = h + + +class Layout(Serialisable): + + tagname = "layout" + + manualLayout = Typed(expected_type=ManualLayout, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('manualLayout',) + + def __init__(self, + manualLayout=None, + extLst=None, + ): + self.manualLayout = manualLayout diff --git a/venv/Lib/site-packages/openpyxl/chart/legend.py b/venv/Lib/site-packages/openpyxl/chart/legend.py new file mode 100644 index 0000000..1f7c802 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/legend.py @@ -0,0 +1,75 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Integer, + Alias, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedBool, + NestedSet, + NestedInteger +) + +from .layout import Layout +from .shapes import GraphicalProperties +from .text import RichText + + +class LegendEntry(Serialisable): + + tagname = "legendEntry" + + idx = NestedInteger() + delete = NestedBool() + txPr = Typed(expected_type=RichText, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('idx', 'delete', 'txPr') + + def __init__(self, + idx=0, + delete=False, + txPr=None, + extLst=None, + ): + self.idx = idx + self.delete = delete + self.txPr = txPr + + +class Legend(Serialisable): + + tagname = "legend" + + legendPos = NestedSet(values=(['b', 'tr', 'l', 'r', 't'])) + position = Alias('legendPos') + legendEntry = Sequence(expected_type=LegendEntry) + layout = Typed(expected_type=Layout, allow_none=True) + overlay = NestedBool(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + txPr = Typed(expected_type=RichText, allow_none=True) + textProperties = Alias('txPr') + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('legendPos', 'legendEntry', 'layout', 'overlay', 'spPr', 'txPr',) + + def __init__(self, + legendPos="r", + legendEntry=(), + layout=None, + overlay=None, + spPr=None, + txPr=None, + extLst=None, + ): + self.legendPos = legendPos + self.legendEntry = legendEntry + self.layout = layout + self.overlay = overlay + self.spPr = spPr + self.txPr = txPr diff --git a/venv/Lib/site-packages/openpyxl/chart/line_chart.py b/venv/Lib/site-packages/openpyxl/chart/line_chart.py new file mode 100644 index 0000000..0aa3ad5 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/line_chart.py @@ -0,0 +1,129 @@ +#Autogenerated schema +from openpyxl.descriptors import ( + Typed, + Sequence, + Alias, + ) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedSet, + NestedBool, +) + +from ._chart import ChartBase +from .updown_bars import UpDownBars +from .descriptors import NestedGapAmount +from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines, _BaseAxis +from .label import DataLabelList +from .series import Series + + +class _LineChartBase(ChartBase): + + grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked'])) + varyColors = NestedBool(allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + dropLines = Typed(expected_type=ChartLines, allow_none=True) + + _series_type = "line" + + __elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines') + + def __init__(self, + grouping="standard", + varyColors=None, + ser=(), + dLbls=None, + dropLines=None, + **kw + ): + self.grouping = grouping + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + self.dropLines = dropLines + super().__init__(**kw) + + +class LineChart(_LineChartBase): + + tagname = "lineChart" + + grouping = _LineChartBase.grouping + varyColors = _LineChartBase.varyColors + ser = _LineChartBase.ser + dLbls = _LineChartBase.dLbls + dropLines =_LineChartBase.dropLines + + hiLowLines = Typed(expected_type=ChartLines, allow_none=True) + upDownBars = Typed(expected_type=UpDownBars, allow_none=True) + marker = NestedBool(allow_none=True) + smooth = NestedBool(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=_BaseAxis) + y_axis = Typed(expected_type=NumericAxis) + + __elements__ = _LineChartBase.__elements__ + ('hiLowLines', 'upDownBars', 'marker', 'smooth', 'axId') + + def __init__(self, + hiLowLines=None, + upDownBars=None, + marker=None, + smooth=None, + extLst=None, + **kw + ): + self.hiLowLines = hiLowLines + self.upDownBars = upDownBars + self.marker = marker + self.smooth = smooth + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + + super().__init__(**kw) + + +class LineChart3D(_LineChartBase): + + tagname = "line3DChart" + + grouping = _LineChartBase.grouping + varyColors = _LineChartBase.varyColors + ser = _LineChartBase.ser + dLbls = _LineChartBase.dLbls + dropLines =_LineChartBase.dropLines + + gapDepth = NestedGapAmount() + hiLowLines = Typed(expected_type=ChartLines, allow_none=True) + upDownBars = Typed(expected_type=UpDownBars, allow_none=True) + marker = NestedBool(allow_none=True) + smooth = NestedBool(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + z_axis = Typed(expected_type=SeriesAxis) + + __elements__ = _LineChartBase.__elements__ + ('gapDepth', 'hiLowLines', + 'upDownBars', 'marker', 'smooth', 'axId') + + def __init__(self, + gapDepth=None, + hiLowLines=None, + upDownBars=None, + marker=None, + smooth=None, + **kw + ): + self.gapDepth = gapDepth + self.hiLowLines = hiLowLines + self.upDownBars = upDownBars + self.marker = marker + self.smooth = smooth + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + self.z_axis = SeriesAxis() + super(LineChart3D, self).__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/marker.py b/venv/Lib/site-packages/openpyxl/chart/marker.py new file mode 100644 index 0000000..61e2641 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/marker.py @@ -0,0 +1,90 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Alias, +) + +from openpyxl.descriptors.excel import( + ExtensionList, + _explicit_none, +) + +from openpyxl.descriptors.nested import ( + NestedBool, + NestedInteger, + NestedMinMax, + NestedNoneSet, +) + +from .layout import Layout +from .picture import PictureOptions +from .shapes import * +from .text import * +from .error_bar import * + + +class Marker(Serialisable): + + tagname = "marker" + + symbol = NestedNoneSet(values=(['circle', 'dash', 'diamond', 'dot', 'picture', + 'plus', 'square', 'star', 'triangle', 'x', 'auto']), + to_tree=_explicit_none) + size = NestedMinMax(min=2, max=72, allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('symbol', 'size', 'spPr') + + def __init__(self, + symbol=None, + size=None, + spPr=None, + extLst=None, + ): + self.symbol = symbol + self.size = size + if spPr is None: + spPr = GraphicalProperties() + self.spPr = spPr + + +class DataPoint(Serialisable): + + tagname = "dPt" + + idx = NestedInteger() + invertIfNegative = NestedBool(allow_none=True) + marker = Typed(expected_type=Marker, allow_none=True) + bubble3D = NestedBool(allow_none=True) + explosion = NestedInteger(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + pictureOptions = Typed(expected_type=PictureOptions, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('idx', 'invertIfNegative', 'marker', 'bubble3D', + 'explosion', 'spPr', 'pictureOptions') + + def __init__(self, + idx=None, + invertIfNegative=None, + marker=None, + bubble3D=None, + explosion=None, + spPr=None, + pictureOptions=None, + extLst=None, + ): + self.idx = idx + self.invertIfNegative = invertIfNegative + self.marker = marker + self.bubble3D = bubble3D + self.explosion = explosion + if spPr is None: + spPr = GraphicalProperties() + self.spPr = spPr + self.pictureOptions = pictureOptions diff --git a/venv/Lib/site-packages/openpyxl/chart/picture.py b/venv/Lib/site-packages/openpyxl/chart/picture.py new file mode 100644 index 0000000..8c917d8 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/picture.py @@ -0,0 +1,35 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable + +from openpyxl.descriptors.nested import ( + NestedBool, + NestedFloat, + NestedMinMax, + NestedNoneSet, +) + +class PictureOptions(Serialisable): + + tagname = "pictureOptions" + + applyToFront = NestedBool(allow_none=True, nested=True) + applyToSides = NestedBool(allow_none=True, nested=True) + applyToEnd = NestedBool(allow_none=True, nested=True) + pictureFormat = NestedNoneSet(values=(['stretch', 'stack', 'stackScale']), nested=True) + pictureStackUnit = NestedFloat(allow_none=True, nested=True) + + __elements__ = ('applyToFront', 'applyToSides', 'applyToEnd', 'pictureFormat', 'pictureStackUnit') + + def __init__(self, + applyToFront=None, + applyToSides=None, + applyToEnd=None, + pictureFormat=None, + pictureStackUnit=None, + ): + self.applyToFront = applyToFront + self.applyToSides = applyToSides + self.applyToEnd = applyToEnd + self.pictureFormat = pictureFormat + self.pictureStackUnit = pictureStackUnit diff --git a/venv/Lib/site-packages/openpyxl/chart/pie_chart.py b/venv/Lib/site-packages/openpyxl/chart/pie_chart.py new file mode 100644 index 0000000..6bb67e1 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/pie_chart.py @@ -0,0 +1,177 @@ +#Autogenerated schema +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Bool, + MinMax, + Integer, + NoneSet, + Float, + Alias, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList, Percentage +from openpyxl.descriptors.nested import ( + NestedBool, + NestedMinMax, + NestedInteger, + NestedFloat, + NestedNoneSet, + NestedSet, +) +from openpyxl.descriptors.sequence import ValueSequence + +from ._chart import ChartBase +from .axis import ChartLines +from .descriptors import NestedGapAmount +from .series import Series +from .label import DataLabelList + + +class _PieChartBase(ChartBase): + + varyColors = NestedBool(allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + + _series_type = "pie" + + __elements__ = ('varyColors', 'ser', 'dLbls') + + def __init__(self, + varyColors=True, + ser=(), + dLbls=None, + ): + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + super().__init__() + + + +class PieChart(_PieChartBase): + + tagname = "pieChart" + + varyColors = _PieChartBase.varyColors + ser = _PieChartBase.ser + dLbls = _PieChartBase.dLbls + + firstSliceAng = NestedMinMax(min=0, max=360) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _PieChartBase.__elements__ + ('firstSliceAng', ) + + def __init__(self, + firstSliceAng=0, + extLst=None, + **kw + ): + self.firstSliceAng = firstSliceAng + super().__init__(**kw) + + +class PieChart3D(_PieChartBase): + + tagname = "pie3DChart" + + varyColors = _PieChartBase.varyColors + ser = _PieChartBase.ser + dLbls = _PieChartBase.dLbls + + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _PieChartBase.__elements__ + + +class DoughnutChart(_PieChartBase): + + tagname = "doughnutChart" + + varyColors = _PieChartBase.varyColors + ser = _PieChartBase.ser + dLbls = _PieChartBase.dLbls + + firstSliceAng = NestedMinMax(min=0, max=360) + holeSize = NestedMinMax(min=1, max=90, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _PieChartBase.__elements__ + ('firstSliceAng', 'holeSize') + + def __init__(self, + firstSliceAng=0, + holeSize=10, + extLst=None, + **kw + ): + self.firstSliceAng = firstSliceAng + self.holeSize = holeSize + super().__init__(**kw) + + +class CustomSplit(Serialisable): + + tagname = "custSplit" + + secondPiePt = ValueSequence(expected_type=int) + + __elements__ = ('secondPiePt',) + + def __init__(self, + secondPiePt=(), + ): + self.secondPiePt = secondPiePt + + +class ProjectedPieChart(_PieChartBase): + + """ + From the spec 21.2.2.126 + + This element contains the pie of pie or bar of pie series on this + chart. Only the first series shall be displayed. The splitType element + shall determine whether the splitPos and custSplit elements apply. + """ + + tagname = "ofPieChart" + + varyColors = _PieChartBase.varyColors + ser = _PieChartBase.ser + dLbls = _PieChartBase.dLbls + + ofPieType = NestedSet(values=(['pie', 'bar'])) + type = Alias('ofPieType') + gapWidth = NestedGapAmount() + splitType = NestedNoneSet(values=(['auto', 'cust', 'percent', 'pos', 'val'])) + splitPos = NestedFloat(allow_none=True) + custSplit = Typed(expected_type=CustomSplit, allow_none=True) + secondPieSize = NestedMinMax(min=5, max=200, allow_none=True) + serLines = Typed(expected_type=ChartLines, allow_none=True) + join_lines = Alias('serLines') + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = _PieChartBase.__elements__ + ('ofPieType', 'gapWidth', + 'splitType', 'splitPos', 'custSplit', 'secondPieSize', 'serLines') + + def __init__(self, + ofPieType="pie", + gapWidth=None, + splitType="auto", + splitPos=None, + custSplit=None, + secondPieSize=75, + serLines=None, + extLst=None, + **kw + ): + self.ofPieType = ofPieType + self.gapWidth = gapWidth + self.splitType = splitType + self.splitPos = splitPos + self.custSplit = custSplit + self.secondPieSize = secondPieSize + if serLines is None: + self.serLines = ChartLines() + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/pivot.py b/venv/Lib/site-packages/openpyxl/chart/pivot.py new file mode 100644 index 0000000..937fd29 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/pivot.py @@ -0,0 +1,65 @@ + +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Alias, + Typed, +) +from openpyxl.descriptors.nested import NestedInteger, NestedText +from openpyxl.descriptors.excel import ExtensionList + +from .label import DataLabel +from .marker import Marker +from .shapes import GraphicalProperties +from .text import RichText + + +class PivotSource(Serialisable): + + tagname = "pivotSource" + + name = NestedText(expected_type=str) + fmtId = NestedInteger(expected_type=int) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('name', 'fmtId') + + def __init__(self, + name=None, + fmtId=None, + extLst=None, + ): + self.name = name + self.fmtId = fmtId + + +class PivotFormat(Serialisable): + + tagname = "pivotFmt" + + idx = NestedInteger(nested=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + txPr = Typed(expected_type=RichText, allow_none=True) + TextBody = Alias("txPr") + marker = Typed(expected_type=Marker, allow_none=True) + dLbl = Typed(expected_type=DataLabel, allow_none=True) + DataLabel = Alias("dLbl") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('idx', 'spPr', 'txPr', 'marker', 'dLbl') + + def __init__(self, + idx=0, + spPr=None, + txPr=None, + marker=None, + dLbl=None, + extLst=None, + ): + self.idx = idx + self.spPr = spPr + self.txPr = txPr + self.marker = marker + self.dLbl = dLbl diff --git a/venv/Lib/site-packages/openpyxl/chart/plotarea.py b/venv/Lib/site-packages/openpyxl/chart/plotarea.py new file mode 100644 index 0000000..268bfbc --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/plotarea.py @@ -0,0 +1,162 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Alias, +) +from openpyxl.descriptors.excel import ( + ExtensionList, +) +from openpyxl.descriptors.sequence import ( + MultiSequence, + MultiSequencePart, +) +from openpyxl.descriptors.nested import ( + NestedBool, +) + +from ._3d import _3DBase +from .area_chart import AreaChart, AreaChart3D +from .bar_chart import BarChart, BarChart3D +from .bubble_chart import BubbleChart +from .line_chart import LineChart, LineChart3D +from .pie_chart import PieChart, PieChart3D, ProjectedPieChart, DoughnutChart +from .radar_chart import RadarChart +from .scatter_chart import ScatterChart +from .stock_chart import StockChart +from .surface_chart import SurfaceChart, SurfaceChart3D +from .layout import Layout +from .shapes import GraphicalProperties +from .text import RichText + +from .axis import ( + NumericAxis, + TextAxis, + SeriesAxis, + DateAxis, +) + + +class DataTable(Serialisable): + + tagname = "dTable" + + showHorzBorder = NestedBool(allow_none=True) + showVertBorder = NestedBool(allow_none=True) + showOutline = NestedBool(allow_none=True) + showKeys = NestedBool(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + txPr = Typed(expected_type=RichText, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('showHorzBorder', 'showVertBorder', 'showOutline', + 'showKeys', 'spPr', 'txPr') + + def __init__(self, + showHorzBorder=None, + showVertBorder=None, + showOutline=None, + showKeys=None, + spPr=None, + txPr=None, + extLst=None, + ): + self.showHorzBorder = showHorzBorder + self.showVertBorder = showVertBorder + self.showOutline = showOutline + self.showKeys = showKeys + self.spPr = spPr + self.txPr = txPr + + +class PlotArea(Serialisable): + + tagname = "plotArea" + + layout = Typed(expected_type=Layout, allow_none=True) + dTable = Typed(expected_type=DataTable, allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + # at least one chart + _charts = MultiSequence() + areaChart = MultiSequencePart(expected_type=AreaChart, store="_charts") + area3DChart = MultiSequencePart(expected_type=AreaChart3D, store="_charts") + lineChart = MultiSequencePart(expected_type=LineChart, store="_charts") + line3DChart = MultiSequencePart(expected_type=LineChart3D, store="_charts") + stockChart = MultiSequencePart(expected_type=StockChart, store="_charts") + radarChart = MultiSequencePart(expected_type=RadarChart, store="_charts") + scatterChart = MultiSequencePart(expected_type=ScatterChart, store="_charts") + pieChart = MultiSequencePart(expected_type=PieChart, store="_charts") + pie3DChart = MultiSequencePart(expected_type=PieChart3D, store="_charts") + doughnutChart = MultiSequencePart(expected_type=DoughnutChart, store="_charts") + barChart = MultiSequencePart(expected_type=BarChart, store="_charts") + bar3DChart = MultiSequencePart(expected_type=BarChart3D, store="_charts") + ofPieChart = MultiSequencePart(expected_type=ProjectedPieChart, store="_charts") + surfaceChart = MultiSequencePart(expected_type=SurfaceChart, store="_charts") + surface3DChart = MultiSequencePart(expected_type=SurfaceChart3D, store="_charts") + bubbleChart = MultiSequencePart(expected_type=BubbleChart, store="_charts") + + # axes + _axes = MultiSequence() + valAx = MultiSequencePart(expected_type=NumericAxis, store="_axes") + catAx = MultiSequencePart(expected_type=TextAxis, store="_axes") + dateAx = MultiSequencePart(expected_type=DateAxis, store="_axes") + serAx = MultiSequencePart(expected_type=SeriesAxis, store="_axes") + + __elements__ = ('layout', '_charts', '_axes', 'dTable', 'spPr') + + def __init__(self, + layout=None, + dTable=None, + spPr=None, + _charts=(), + _axes=(), + extLst=None, + ): + self.layout = layout + self.dTable = dTable + self.spPr = spPr + self._charts = _charts + self._axes = _axes + + + def to_tree(self, tagname=None, idx=None, namespace=None): + axIds = {ax.axId for ax in self._axes} + for chart in self._charts: + for id, axis in chart._axes.items(): + if id not in axIds: + setattr(self, axis.tagname, axis) + axIds.add(id) + + return super().to_tree(tagname) + + + @classmethod + def from_tree(cls, node): + self = super().from_tree(node) + axes = dict((axis.axId, axis) for axis in self._axes) + for chart in self._charts: + if isinstance(chart, (ScatterChart, BubbleChart)): + x, y = (axes[axId] for axId in chart.axId) + chart.x_axis = x + chart.y_axis = y + continue + + for axId in chart.axId: + axis = axes.get(axId) + if axis is None and isinstance(chart, _3DBase): + # Series Axis can be optional + chart.z_axis = None + continue + if axis.tagname in ("catAx", "dateAx"): + chart.x_axis = axis + elif axis.tagname == "valAx": + chart.y_axis = axis + elif axis.tagname == "serAx": + chart.z_axis = axis + + return self diff --git a/venv/Lib/site-packages/openpyxl/chart/print_settings.py b/venv/Lib/site-packages/openpyxl/chart/print_settings.py new file mode 100644 index 0000000..6513731 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/print_settings.py @@ -0,0 +1,57 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Float, + Typed, + Alias, +) + +from openpyxl.worksheet.page import PrintPageSetup +from openpyxl.worksheet.header_footer import HeaderFooter + + +class PageMargins(Serialisable): + """ + Identical to openpyxl.worksheet.page.Pagemargins but element names are different :-/ + """ + tagname = "pageMargins" + + l = Float() + left = Alias('l') + r = Float() + right = Alias('r') + t = Float() + top = Alias('t') + b = Float() + bottom = Alias('b') + header = Float() + footer = Float() + + def __init__(self, l=0.75, r=0.75, t=1, b=1, header=0.5, footer=0.5): + self.l = l + self.r = r + self.t = t + self.b = b + self.header = header + self.footer = footer + + +class PrintSettings(Serialisable): + + tagname = "printSettings" + + headerFooter = Typed(expected_type=HeaderFooter, allow_none=True) + pageMargins = Typed(expected_type=PageMargins, allow_none=True) + pageSetup = Typed(expected_type=PrintPageSetup, allow_none=True) + + __elements__ = ("headerFooter", "pageMargins", "pageMargins") + + def __init__(self, + headerFooter=None, + pageMargins=None, + pageSetup=None, + ): + self.headerFooter = headerFooter + self.pageMargins = pageMargins + self.pageSetup = pageSetup diff --git a/venv/Lib/site-packages/openpyxl/chart/radar_chart.py b/venv/Lib/site-packages/openpyxl/chart/radar_chart.py new file mode 100644 index 0000000..fa3aa0d --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/radar_chart.py @@ -0,0 +1,55 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Sequence, + Typed, + Alias, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedBool, + NestedInteger, + NestedSet +) + +from ._chart import ChartBase +from .axis import TextAxis, NumericAxis +from .series import Series +from .label import DataLabelList + + +class RadarChart(ChartBase): + + tagname = "radarChart" + + radarStyle = NestedSet(values=(['standard', 'marker', 'filled'])) + type = Alias("radarStyle") + varyColors = NestedBool(nested=True, allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + _series_type = "radar" + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + + __elements__ = ('radarStyle', 'varyColors', 'ser', 'dLbls', 'axId') + + def __init__(self, + radarStyle="standard", + varyColors=None, + ser=(), + dLbls=None, + extLst=None, + **kw + ): + self.radarStyle = radarStyle + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/reader.py b/venv/Lib/site-packages/openpyxl/chart/reader.py new file mode 100644 index 0000000..0ef719f --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/reader.py @@ -0,0 +1,32 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Read a chart +""" + +def read_chart(chartspace): + cs = chartspace + plot = cs.chart.plotArea + + chart = plot._charts[0] + chart._charts = plot._charts + + chart.title = cs.chart.title + chart.display_blanks = cs.chart.dispBlanksAs + chart.visible_cells_only = cs.chart.plotVisOnly + chart.layout = plot.layout + chart.legend = cs.chart.legend + + # 3d attributes + chart.floor = cs.chart.floor + chart.sideWall = cs.chart.sideWall + chart.backWall = cs.chart.backWall + chart.pivotSource = cs.pivotSource + chart.pivotFormats = cs.chart.pivotFmts + chart.idx_base = min((s.idx for s in chart.series), default=0) + chart._reindex() + + # Border, fill, etc. + chart.graphical_properties = cs.graphical_properties + + return chart diff --git a/venv/Lib/site-packages/openpyxl/chart/reference.py b/venv/Lib/site-packages/openpyxl/chart/reference.py new file mode 100644 index 0000000..dc10279 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/reference.py @@ -0,0 +1,124 @@ +# Copyright (c) 2010-2024 openpyxl + +from itertools import chain + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + MinMax, + Typed, + String, + Strict, +) +from openpyxl.worksheet.worksheet import Worksheet +from openpyxl.utils import ( + get_column_letter, + range_to_tuple, + quote_sheetname +) + + +class DummyWorksheet: + + + def __init__(self, title): + self.title = title + + +class Reference(Strict): + + """ + Normalise cell range references + """ + + min_row = MinMax(min=1, max=1000000, expected_type=int) + max_row = MinMax(min=1, max=1000000, expected_type=int) + min_col = MinMax(min=1, max=16384, expected_type=int) + max_col = MinMax(min=1, max=16384, expected_type=int) + range_string = String(allow_none=True) + + def __init__(self, + worksheet=None, + min_col=None, + min_row=None, + max_col=None, + max_row=None, + range_string=None + ): + if range_string is not None: + sheetname, boundaries = range_to_tuple(range_string) + min_col, min_row, max_col, max_row = boundaries + worksheet = DummyWorksheet(sheetname) + + self.worksheet = worksheet + self.min_col = min_col + self.min_row = min_row + if max_col is None: + max_col = min_col + self.max_col = max_col + if max_row is None: + max_row = min_row + self.max_row = max_row + + + def __repr__(self): + return str(self) + + + def __str__(self): + fmt = u"{0}!${1}${2}:${3}${4}" + if (self.min_col == self.max_col + and self.min_row == self.max_row): + fmt = u"{0}!${1}${2}" + return fmt.format(self.sheetname, + get_column_letter(self.min_col), self.min_row, + get_column_letter(self.max_col), self.max_row + ) + + + __str__ = __str__ + + + + def __len__(self): + if self.min_row == self.max_row: + return 1 + self.max_col - self.min_col + return 1 + self.max_row - self.min_row + + + def __eq__(self, other): + return str(self) == str(other) + + + @property + def rows(self): + """ + Return all rows in the range + """ + for row in range(self.min_row, self.max_row+1): + yield Reference(self.worksheet, self.min_col, row, self.max_col, row) + + + @property + def cols(self): + """ + Return all columns in the range + """ + for col in range(self.min_col, self.max_col+1): + yield Reference(self.worksheet, col, self.min_row, col, self.max_row) + + + def pop(self): + """ + Return and remove the first cell + """ + cell = "{0}{1}".format(get_column_letter(self.min_col), self.min_row) + if self.min_row == self.max_row: + self.min_col += 1 + else: + self.min_row += 1 + return cell + + + @property + def sheetname(self): + return quote_sheetname(self.worksheet.title) diff --git a/venv/Lib/site-packages/openpyxl/chart/scatter_chart.py b/venv/Lib/site-packages/openpyxl/chart/scatter_chart.py new file mode 100644 index 0000000..2699239 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/scatter_chart.py @@ -0,0 +1,53 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Sequence, + Alias +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedNoneSet, + NestedBool, +) + +from ._chart import ChartBase +from .axis import NumericAxis, TextAxis +from .series import XYSeries +from .label import DataLabelList + + +class ScatterChart(ChartBase): + + tagname = "scatterChart" + + scatterStyle = NestedNoneSet(values=(['line', 'lineMarker', 'marker', 'smooth', 'smoothMarker'])) + varyColors = NestedBool(allow_none=True) + ser = Sequence(expected_type=XYSeries, allow_none=True) + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias("dLbls") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=(NumericAxis, TextAxis)) + y_axis = Typed(expected_type=NumericAxis) + + _series_type = "scatter" + + __elements__ = ('scatterStyle', 'varyColors', 'ser', 'dLbls', 'axId',) + + def __init__(self, + scatterStyle=None, + varyColors=None, + ser=(), + dLbls=None, + extLst=None, + **kw + ): + self.scatterStyle = scatterStyle + self.varyColors = varyColors + self.ser = ser + self.dLbls = dLbls + self.x_axis = NumericAxis(axId=10, crossAx=20) + self.y_axis = NumericAxis(axId=20, crossAx=10) + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/series.py b/venv/Lib/site-packages/openpyxl/chart/series.py new file mode 100644 index 0000000..f1403a6 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/series.py @@ -0,0 +1,197 @@ +# Copyright (c) 2010-2024 openpyxl + + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + String, + Integer, + Bool, + Alias, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedInteger, + NestedBool, + NestedNoneSet, + NestedText, +) + +from .shapes import GraphicalProperties +from .data_source import ( + AxDataSource, + NumDataSource, + NumRef, + StrRef, +) +from .error_bar import ErrorBars +from .label import DataLabelList +from .marker import DataPoint, PictureOptions, Marker +from .trendline import Trendline + +attribute_mapping = { + 'area': ('idx', 'order', 'tx', 'spPr', 'pictureOptions', 'dPt', 'dLbls', 'errBars', + 'trendline', 'cat', 'val',), + 'bar':('idx', 'order','tx', 'spPr', 'invertIfNegative', 'pictureOptions', 'dPt', + 'dLbls', 'trendline', 'errBars', 'cat', 'val', 'shape'), + 'bubble':('idx','order', 'tx', 'spPr', 'invertIfNegative', 'dPt', 'dLbls', + 'trendline', 'errBars', 'xVal', 'yVal', 'bubbleSize', 'bubble3D'), + 'line':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline', + 'errBars', 'cat', 'val', 'smooth'), + 'pie':('idx', 'order', 'tx', 'spPr', 'explosion', 'dPt', 'dLbls', 'cat', 'val'), + 'radar':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'cat', 'val'), + 'scatter':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline', + 'errBars', 'xVal', 'yVal', 'smooth'), + 'surface':('idx', 'order', 'tx', 'spPr', 'cat', 'val'), + } + + +class SeriesLabel(Serialisable): + + tagname = "tx" + + strRef = Typed(expected_type=StrRef, allow_none=True) + v = NestedText(expected_type=str, allow_none=True) + value = Alias('v') + + __elements__ = ('strRef', 'v') + + def __init__(self, + strRef=None, + v=None): + self.strRef = strRef + self.v = v + + +class Series(Serialisable): + + """ + Generic series object. Should not be instantiated directly. + User the chart.Series factory instead. + """ + + tagname = "ser" + + idx = NestedInteger() + order = NestedInteger() + tx = Typed(expected_type=SeriesLabel, allow_none=True) + title = Alias('tx') + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + + # area chart + pictureOptions = Typed(expected_type=PictureOptions, allow_none=True) + dPt = Sequence(expected_type=DataPoint, allow_none=True) + data_points = Alias("dPt") + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + labels = Alias("dLbls") + trendline = Typed(expected_type=Trendline, allow_none=True) + errBars = Typed(expected_type=ErrorBars, allow_none=True) + cat = Typed(expected_type=AxDataSource, allow_none=True) + identifiers = Alias("cat") + val = Typed(expected_type=NumDataSource, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + #bar chart + invertIfNegative = NestedBool(allow_none=True) + shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax'])) + + #bubble chart + xVal = Typed(expected_type=AxDataSource, allow_none=True) + yVal = Typed(expected_type=NumDataSource, allow_none=True) + bubbleSize = Typed(expected_type=NumDataSource, allow_none=True) + zVal = Alias("bubbleSize") + bubble3D = NestedBool(allow_none=True) + + #line chart + marker = Typed(expected_type=Marker, allow_none=True) + smooth = NestedBool(allow_none=True) + + #pie chart + explosion = NestedInteger(allow_none=True) + + __elements__ = () + + + def __init__(self, + idx=0, + order=0, + tx=None, + spPr=None, + pictureOptions=None, + dPt=(), + dLbls=None, + trendline=None, + errBars=None, + cat=None, + val=None, + invertIfNegative=None, + shape=None, + xVal=None, + yVal=None, + bubbleSize=None, + bubble3D=None, + marker=None, + smooth=None, + explosion=None, + extLst=None, + ): + self.idx = idx + self.order = order + self.tx = tx + if spPr is None: + spPr = GraphicalProperties() + self.spPr = spPr + self.pictureOptions = pictureOptions + self.dPt = dPt + self.dLbls = dLbls + self.trendline = trendline + self.errBars = errBars + self.cat = cat + self.val = val + self.invertIfNegative = invertIfNegative + self.shape = shape + self.xVal = xVal + self.yVal = yVal + self.bubbleSize = bubbleSize + self.bubble3D = bubble3D + if marker is None: + marker = Marker() + self.marker = marker + self.smooth = smooth + self.explosion = explosion + + + def to_tree(self, tagname=None, idx=None): + """The index can need rebasing""" + if idx is not None: + if self.order == self.idx: + self.order = idx # rebase the order if the index has been rebased + self.idx = idx + return super().to_tree(tagname) + + +class XYSeries(Series): + + """Dedicated series for charts that have x and y series""" + + idx = Series.idx + order = Series.order + tx = Series.tx + spPr = Series.spPr + + dPt = Series.dPt + dLbls = Series.dLbls + trendline = Series.trendline + errBars = Series.errBars + xVal = Series.xVal + yVal = Series.yVal + + invertIfNegative = Series.invertIfNegative + + bubbleSize = Series.bubbleSize + bubble3D = Series.bubble3D + + marker = Series.marker + smooth = Series.smooth diff --git a/venv/Lib/site-packages/openpyxl/chart/series_factory.py b/venv/Lib/site-packages/openpyxl/chart/series_factory.py new file mode 100644 index 0000000..90b368d --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/series_factory.py @@ -0,0 +1,41 @@ +# Copyright (c) 2010-2024 openpyxl + +from .data_source import NumDataSource, NumRef, AxDataSource +from .reference import Reference +from .series import Series, XYSeries, SeriesLabel, StrRef +from openpyxl.utils import rows_from_range, quote_sheetname + + +def SeriesFactory(values, xvalues=None, zvalues=None, title=None, title_from_data=False): + """ + Convenience Factory for creating chart data series. + """ + + if not isinstance(values, Reference): + values = Reference(range_string=values) + + if title_from_data: + cell = values.pop() + title = u"{0}!{1}".format(values.sheetname, cell) + title = SeriesLabel(strRef=StrRef(title)) + elif title is not None: + title = SeriesLabel(v=title) + + source = NumDataSource(numRef=NumRef(f=values)) + if xvalues is not None: + if not isinstance(xvalues, Reference): + xvalues = Reference(range_string=xvalues) + series = XYSeries() + series.yVal = source + series.xVal = AxDataSource(numRef=NumRef(f=xvalues)) + if zvalues is not None: + if not isinstance(zvalues, Reference): + zvalues = Reference(range_string=zvalues) + series.zVal = NumDataSource(NumRef(f=zvalues)) + else: + series = Series() + series.val = source + + if title is not None: + series.title = title + return series diff --git a/venv/Lib/site-packages/openpyxl/chart/shapes.py b/venv/Lib/site-packages/openpyxl/chart/shapes.py new file mode 100644 index 0000000..7736c1a --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/shapes.py @@ -0,0 +1,89 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Alias +) +from openpyxl.descriptors.nested import ( + EmptyTag +) +from openpyxl.drawing.colors import ColorChoiceDescriptor +from openpyxl.drawing.fill import * +from openpyxl.drawing.line import LineProperties +from openpyxl.drawing.geometry import ( + Shape3D, + Scene3D, + Transform2D, + CustomGeometry2D, + PresetGeometry2D, +) + + +class GraphicalProperties(Serialisable): + + """ + Somewhat vaguely 21.2.2.197 says this: + + This element specifies the formatting for the parent chart element. The + custGeom, prstGeom, scene3d, and xfrm elements are not supported. The + bwMode attribute is not supported. + + This doesn't leave much. And the element is used in different places. + """ + + tagname = "spPr" + + bwMode = NoneSet(values=(['clr', 'auto', 'gray', 'ltGray', 'invGray', + 'grayWhite', 'blackGray', 'blackWhite', 'black', 'white', 'hidden'] + ) + ) + + xfrm = Typed(expected_type=Transform2D, allow_none=True) + transform = Alias('xfrm') + custGeom = Typed(expected_type=CustomGeometry2D, allow_none=True) # either or + prstGeom = Typed(expected_type=PresetGeometry2D, allow_none=True) + + # fills one of + noFill = EmptyTag(namespace=DRAWING_NS) + solidFill = ColorChoiceDescriptor() + gradFill = Typed(expected_type=GradientFillProperties, allow_none=True) + pattFill = Typed(expected_type=PatternFillProperties, allow_none=True) + + ln = Typed(expected_type=LineProperties, allow_none=True) + line = Alias('ln') + scene3d = Typed(expected_type=Scene3D, allow_none=True) + sp3d = Typed(expected_type=Shape3D, allow_none=True) + shape3D = Alias('sp3d') + extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True) + + __elements__ = ('xfrm', 'prstGeom', 'noFill', 'solidFill', 'gradFill', 'pattFill', + 'ln', 'scene3d', 'sp3d') + + def __init__(self, + bwMode=None, + xfrm=None, + noFill=None, + solidFill=None, + gradFill=None, + pattFill=None, + ln=None, + scene3d=None, + custGeom=None, + prstGeom=None, + sp3d=None, + extLst=None, + ): + self.bwMode = bwMode + self.xfrm = xfrm + self.noFill = noFill + self.solidFill = solidFill + self.gradFill = gradFill + self.pattFill = pattFill + if ln is None: + ln = LineProperties() + self.ln = ln + self.custGeom = custGeom + self.prstGeom = prstGeom + self.scene3d = scene3d + self.sp3d = sp3d diff --git a/venv/Lib/site-packages/openpyxl/chart/stock_chart.py b/venv/Lib/site-packages/openpyxl/chart/stock_chart.py new file mode 100644 index 0000000..119c790 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/stock_chart.py @@ -0,0 +1,54 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Sequence, + Alias, +) +from openpyxl.descriptors.excel import ExtensionList + +from ._chart import ChartBase +from .axis import TextAxis, NumericAxis, ChartLines +from .updown_bars import UpDownBars +from .label import DataLabelList +from .series import Series + + +class StockChart(ChartBase): + + tagname = "stockChart" + + ser = Sequence(expected_type=Series) #min 3, max4 + dLbls = Typed(expected_type=DataLabelList, allow_none=True) + dataLabels = Alias('dLbls') + dropLines = Typed(expected_type=ChartLines, allow_none=True) + hiLowLines = Typed(expected_type=ChartLines, allow_none=True) + upDownBars = Typed(expected_type=UpDownBars, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + + _series_type = "line" + + __elements__ = ('ser', 'dLbls', 'dropLines', 'hiLowLines', 'upDownBars', + 'axId') + + def __init__(self, + ser=(), + dLbls=None, + dropLines=None, + hiLowLines=None, + upDownBars=None, + extLst=None, + **kw + ): + self.ser = ser + self.dLbls = dLbls + self.dropLines = dropLines + self.hiLowLines = hiLowLines + self.upDownBars = upDownBars + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + super().__init__(**kw) diff --git a/venv/Lib/site-packages/openpyxl/chart/surface_chart.py b/venv/Lib/site-packages/openpyxl/chart/surface_chart.py new file mode 100644 index 0000000..5f388e1 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/surface_chart.py @@ -0,0 +1,119 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Integer, + Bool, + Alias, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedInteger, + NestedBool, +) + +from ._chart import ChartBase +from ._3d import _3DBase +from .axis import TextAxis, NumericAxis, SeriesAxis +from .shapes import GraphicalProperties +from .series import Series + + +class BandFormat(Serialisable): + + tagname = "bandFmt" + + idx = NestedInteger() + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + + __elements__ = ('idx', 'spPr') + + def __init__(self, + idx=0, + spPr=None, + ): + self.idx = idx + self.spPr = spPr + + +class BandFormatList(Serialisable): + + tagname = "bandFmts" + + bandFmt = Sequence(expected_type=BandFormat, allow_none=True) + + __elements__ = ('bandFmt',) + + def __init__(self, + bandFmt=(), + ): + self.bandFmt = bandFmt + + +class _SurfaceChartBase(ChartBase): + + wireframe = NestedBool(allow_none=True) + ser = Sequence(expected_type=Series, allow_none=True) + bandFmts = Typed(expected_type=BandFormatList, allow_none=True) + + _series_type = "surface" + + __elements__ = ('wireframe', 'ser', 'bandFmts') + + def __init__(self, + wireframe=None, + ser=(), + bandFmts=None, + **kw + ): + self.wireframe = wireframe + self.ser = ser + self.bandFmts = bandFmts + super().__init__(**kw) + + +class SurfaceChart3D(_SurfaceChartBase, _3DBase): + + tagname = "surface3DChart" + + wireframe = _SurfaceChartBase.wireframe + ser = _SurfaceChartBase.ser + bandFmts = _SurfaceChartBase.bandFmts + + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + x_axis = Typed(expected_type=TextAxis) + y_axis = Typed(expected_type=NumericAxis) + z_axis = Typed(expected_type=SeriesAxis) + + __elements__ = _SurfaceChartBase.__elements__ + ('axId',) + + def __init__(self, **kw): + self.x_axis = TextAxis() + self.y_axis = NumericAxis() + self.z_axis = SeriesAxis() + super(SurfaceChart3D, self).__init__(**kw) + + +class SurfaceChart(SurfaceChart3D): + + tagname = "surfaceChart" + + wireframe = _SurfaceChartBase.wireframe + ser = _SurfaceChartBase.ser + bandFmts = _SurfaceChartBase.bandFmts + + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = SurfaceChart3D.__elements__ + + def __init__(self, **kw): + super().__init__(**kw) + self.y_axis.delete = True + self.view3D.x_rotation = 90 + self.view3D.y_rotation = 0 + self.view3D.perspective = False + self.view3D.right_angle_axes = False diff --git a/venv/Lib/site-packages/openpyxl/chart/text.py b/venv/Lib/site-packages/openpyxl/chart/text.py new file mode 100644 index 0000000..bd034c2 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/text.py @@ -0,0 +1,78 @@ +# Copyright (c) 2010-2024 openpyxl +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Alias, + Sequence, +) + + +from openpyxl.drawing.text import ( + RichTextProperties, + ListStyle, + Paragraph, +) + +from .data_source import StrRef + + +class RichText(Serialisable): + + """ + From the specification: 21.2.2.216 + + This element specifies text formatting. The lstStyle element is not supported. + """ + + tagname = "rich" + + bodyPr = Typed(expected_type=RichTextProperties) + properties = Alias("bodyPr") + lstStyle = Typed(expected_type=ListStyle, allow_none=True) + p = Sequence(expected_type=Paragraph) + paragraphs = Alias('p') + + __elements__ = ("bodyPr", "lstStyle", "p") + + def __init__(self, + bodyPr=None, + lstStyle=None, + p=None, + ): + if bodyPr is None: + bodyPr = RichTextProperties() + self.bodyPr = bodyPr + self.lstStyle = lstStyle + if p is None: + p = [Paragraph()] + self.p = p + + +class Text(Serialisable): + + """ + The value can be either a cell reference or a text element + If both are present then the reference will be used. + """ + + tagname = "tx" + + strRef = Typed(expected_type=StrRef, allow_none=True) + rich = Typed(expected_type=RichText, allow_none=True) + + __elements__ = ("strRef", "rich") + + def __init__(self, + strRef=None, + rich=None + ): + self.strRef = strRef + if rich is None: + rich = RichText() + self.rich = rich + + + def to_tree(self, tagname=None, idx=None, namespace=None): + if self.strRef and self.rich: + self.rich = None # can only have one + return super().to_tree(tagname, idx, namespace) diff --git a/venv/Lib/site-packages/openpyxl/chart/title.py b/venv/Lib/site-packages/openpyxl/chart/title.py new file mode 100644 index 0000000..10f79d7 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/title.py @@ -0,0 +1,76 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Alias, +) + +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import NestedBool + +from .text import Text, RichText +from .layout import Layout +from .shapes import GraphicalProperties + +from openpyxl.drawing.text import ( + Paragraph, + RegularTextRun, + LineBreak, + ParagraphProperties, + CharacterProperties, +) + + +class Title(Serialisable): + tagname = "title" + + tx = Typed(expected_type=Text, allow_none=True) + text = Alias('tx') + layout = Typed(expected_type=Layout, allow_none=True) + overlay = NestedBool(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + txPr = Typed(expected_type=RichText, allow_none=True) + body = Alias('txPr') + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('tx', 'layout', 'overlay', 'spPr', 'txPr') + + def __init__(self, + tx=None, + layout=None, + overlay=None, + spPr=None, + txPr=None, + extLst=None, + ): + if tx is None: + tx = Text() + self.tx = tx + self.layout = layout + self.overlay = overlay + self.spPr = spPr + self.txPr = txPr + + + +def title_maker(text): + title = Title() + paraprops = ParagraphProperties() + paraprops.defRPr = CharacterProperties() + paras = [Paragraph(r=[RegularTextRun(t=s)], pPr=paraprops) for s in text.split("\n")] + + title.tx.rich.paragraphs = paras + return title + + +class TitleDescriptor(Typed): + + expected_type = Title + allow_none = True + + def __set__(self, instance, value): + if isinstance(value, str): + value = title_maker(value) + super().__set__(instance, value) diff --git a/venv/Lib/site-packages/openpyxl/chart/trendline.py b/venv/Lib/site-packages/openpyxl/chart/trendline.py new file mode 100644 index 0000000..bf6d236 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/trendline.py @@ -0,0 +1,98 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + String, + Alias +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.nested import ( + NestedBool, + NestedInteger, + NestedFloat, + NestedSet +) + +from .data_source import NumFmt +from .shapes import GraphicalProperties +from .text import RichText, Text +from .layout import Layout + + +class TrendlineLabel(Serialisable): + + tagname = "trendlineLbl" + + layout = Typed(expected_type=Layout, allow_none=True) + tx = Typed(expected_type=Text, allow_none=True) + numFmt = Typed(expected_type=NumFmt, allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias("spPr") + txPr = Typed(expected_type=RichText, allow_none=True) + textProperties = Alias("txPr") + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('layout', 'tx', 'numFmt', 'spPr', 'txPr') + + def __init__(self, + layout=None, + tx=None, + numFmt=None, + spPr=None, + txPr=None, + extLst=None, + ): + self.layout = layout + self.tx = tx + self.numFmt = numFmt + self.spPr = spPr + self.txPr = txPr + + +class Trendline(Serialisable): + + tagname = "trendline" + + name = String(allow_none=True) + spPr = Typed(expected_type=GraphicalProperties, allow_none=True) + graphicalProperties = Alias('spPr') + trendlineType = NestedSet(values=(['exp', 'linear', 'log', 'movingAvg', 'poly', 'power'])) + order = NestedInteger(allow_none=True) + period = NestedInteger(allow_none=True) + forward = NestedFloat(allow_none=True) + backward = NestedFloat(allow_none=True) + intercept = NestedFloat(allow_none=True) + dispRSqr = NestedBool(allow_none=True) + dispEq = NestedBool(allow_none=True) + trendlineLbl = Typed(expected_type=TrendlineLabel, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('spPr', 'trendlineType', 'order', 'period', 'forward', + 'backward', 'intercept', 'dispRSqr', 'dispEq', 'trendlineLbl') + + def __init__(self, + name=None, + spPr=None, + trendlineType='linear', + order=None, + period=None, + forward=None, + backward=None, + intercept=None, + dispRSqr=None, + dispEq=None, + trendlineLbl=None, + extLst=None, + ): + self.name = name + self.spPr = spPr + self.trendlineType = trendlineType + self.order = order + self.period = period + self.forward = forward + self.backward = backward + self.intercept = intercept + self.dispRSqr = dispRSqr + self.dispEq = dispEq + self.trendlineLbl = trendlineLbl diff --git a/venv/Lib/site-packages/openpyxl/chart/updown_bars.py b/venv/Lib/site-packages/openpyxl/chart/updown_bars.py new file mode 100644 index 0000000..6de7ab8 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chart/updown_bars.py @@ -0,0 +1,31 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import Typed +from openpyxl.descriptors.excel import ExtensionList + +from .shapes import GraphicalProperties +from .axis import ChartLines +from .descriptors import NestedGapAmount + + +class UpDownBars(Serialisable): + + tagname = "upbars" + + gapWidth = NestedGapAmount() + upBars = Typed(expected_type=ChartLines, allow_none=True) + downBars = Typed(expected_type=ChartLines, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('gapWidth', 'upBars', 'downBars') + + def __init__(self, + gapWidth=150, + upBars=None, + downBars=None, + extLst=None, + ): + self.gapWidth = gapWidth + self.upBars = upBars + self.downBars = downBars diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__init__.py b/venv/Lib/site-packages/openpyxl/chartsheet/__init__.py new file mode 100644 index 0000000..1726676 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/chartsheet/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) 2010-2024 openpyxl + +from .chartsheet import Chartsheet diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d98a7365af80390637bd3a8b483b9dc9f04bd25 GIT binary patch literal 249 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/custom.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/custom.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80e469d8d80e74d1c620ce89bb4fda17dddf5603 GIT binary patch literal 2109 zcmZuy&2Jk;6rcU}S8O*QP12;P8|cRhnn-{^gi-`)(^dpiDJh4QrPbCmO_uI@-Pv_o zS3daAL#1+WB`y&Mq>%mrJ#s|if{>A%k&ucwaf_5xl{oRY!?{UQiFVO+08Y>jcDtguLEtIay2BDKQqHdw97V3~Tg;Zj__ z!no^rZs^?dm??|w4QGvg@-zsR(1k4PB5$ z=<6<}tR^xWj5n{vHb|#$I9`K=t6*jv&kOF^wV=kfWHH3<*I6}U)Q&)RJ__fDr)BF0 zlue@(iz;&K2Lf2Grh39*hi{Iluy-5a328|!VuO{mmJD7`K|)#zcs-@SQ^D&c5qKJS z{dkd<4qiW*Ny`8aQax!+vL%&GL#S(z9YPDM4!pe;`aux*tHF{R@o|{VClDq9 z%#=_==H2Gg$ecu&K{$nQcxs4mSL(HY>Ec4=X2^J0Sq&(iTUlDHEIP0!WjA>6EhrdP zs1rH1>(>Jg*aj|%);fA};UE&K?eO?HRL*yJPiyL5N#1az5xH#rMlzB_gHk=jX3bbIdf`A6y> zsmVQ9N=&0%=0z~d(9AL1yyp1KwnfIa{eU(+v~#w7x8Zob5hHTe(Bx@YmxzerNtDFU zBywT^6HN`YvIw!dIke(vV8r8);10}VKC4BcZSz^+w+Md=hw(Lez7Lq2VF2)ubn~a$ zSO3Zu9)H-ryptPwe7${TCs+7=;*(D9Q!tC8n`)9czpBDbJ`hRY=5~^9NR2E zk2=N6z>iF9wtiMSBUjqXFGfCVFYoGPe5#B8rS8ZyKxiYb%5VN7vX*Qg~(%oOAz4WGrwK<{1@6e zzS92s#mKohOtWYA6-Ap**5j(Oc}$f0*J|!w!0*I`axN)V_U-s%!%-wLI+#XTSmka# z3V6ulWR0^pPT)9W@$BNnQPbzx{VMa~{1>N>oB&l~@Rj2DjTYmBd9RO$MK!q?@tugX zJXYecIwEy3xr&$g2kyNV=9FLfdZen}AWM0)p6vhYe)BzZqKEtyX* U?i1+tFJ+|pr^_!1bg^*%0rwUJVE_OC literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/properties.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/properties.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22cc5456fd6dfd3a984cad4d5ec7250120ee5b32 GIT binary patch literal 1080 zcmZuw&1(}u6rb78Bu$!NQ`Dj*p(x~Fdh$|>2Lo+|5`?CgWntK4#%6WDoY~e!a>$_v z4|=Z0o)oDE{|~P{vp=8 zMD(#TTm$70QADwad~9J~u@qmmR4jdpr}?_2k95^DeA6;9QqVf0+5w_E(~s4(j+N;d zHS?!5YHFfA3PUe3wqouEJBi-vMU2*PlHX$7bv#!%ZI6MiH$pGuowP!V+SnLcpd2EG zEKHH5P;99RVj5LGsmD0Yv2^el|9MRCWLOq_+A$0)#mZ6Ln#m&h&%7wqRV?t&r0C)>^}EIHKcF24g;h34~3Z*deYT zg*;~5-ebX@z3H}X;l}J<Nf7n+z2(l7r{!o$R6Xh?8A9B^jR|>m`zkK$ zlkmLk?8>aBJRvW3 z9d8^lV`oRIT#}qpAqhzNkXM_V5+pNnC-a!kf>;p3=fL$5@v;nGlaQT29u%<(aDYx{ zuMgJ0m&!-lN$Jku@mX>HsC-hqJJ>iYmXGd#Zk-fY1{>ezDuc~)1Kp~eE-b=(VVZh1 zEi7v`@?C0u>CdWm2e75NLBI}-2! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/protection.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/protection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3745cd21135b9b08cd19b05e12506afd19f95d88 GIT binary patch literal 1512 zcma)6&u<$=6rTNI@A_v47$DaT>LiaBL(z_7NOLQWnY4DIg!U+x`Q3yE zQP0t2c?%2r&Xuho!hERwUCIN@0)h7!b#z(jW6}2pScrQuC$i{$#N&ke2_?Q-dv3;z z9Dfbu5K-i61i3oVTti3HB>H#86D`Yea}dd&idZj1Y={(2Zq z(q1T1Py&67**=v8F$kh|ybp;5fmxD8E130S9why+gG1W!?YU+!>hM?69W#JKG}1=M z1D4rH2X7`CLL&n_m7m(k1aB@n8s)&7H6Aka;N=#X)))53g2?>np&>ku)^RLeg(SYD z;3Wmi3eG90E2sg0Xr`d-)BlkwRACop_D{ckt$RyQF1j~kLRz~Yw7YFAd`u`PpK918 zIKf^J4q~2A-n~nsyWJ0iy{-rndTD_DJGe(hHy+SvFucz$`-|3H9%M%lde<5ZrR{k^ z6eOPa`TAMyZOx}wVSC~|fH68+M(3Lc=9lH^%0@b@z6wKidU{xY^T3?gjcMuJ52faG z?X`pVzq)Z`pz?)dSOhs%Co`v}wh%#YJrC}O7sh0tDPH!x&-O8!%~%QUDauu6GJ#b` zGUZdzRRgmgsK%ZsE(@NAlY|S;m&QBKvz13zCbc&pR$YEbCe@4M?GyG(?e=)*D32N&)7ACq%gx!Zd2!m< zc(zo_ZDt!#?{+HEQa6AFd$K-nR*O*K^I(v~T=2A*v^G__Y@C(UqW68uxDrIZa%KV? zrNw87TPkmTkq2L%S8+Rv!^ iJG%NKy80Bo{S;mM+cY%&S$R#{e0cqF<1YjxUFcuGsDfVr literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/publish.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/chartsheet/__pycache__/publish.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8ba4960b77a2fb3d0ceb2d09b42f5b1e73cf022 GIT binary patch literal 1995 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 ruRiH)RCb^8+iHYbv4SY literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/comments/__pycache__/comment_sheet.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/comments/__pycache__/comment_sheet.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..709418ced87128159beae768ea617093504bd01d GIT binary patch literal 7233 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 Mp815}og41|06&^q8~^|S literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/comments/__pycache__/comments.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/comments/__pycache__/comments.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c358358118038748d454e81c10875aa3f6c7754f GIT binary patch literal 2897 zcmbtWO>7fa5Poa#+K#iaO%nbRsJ2qn)(UlhP}Pb85={ZA3Jxuyhs4rqv-=WnV(*%_ z&w!0ng(^~mR75!iPQayL<-irV(Du?wy(G@GA0;gEMy2{VWZOs%?o29m5lH_SqgTIMGSGCj71FzXv~NJ?J%N1<3fFg08rM{_Sh5+X zEO(Jw7jwhrM9wieeY>RTGujk&a(0PYrOM^PJG$??)0|{V6*s1;re$(ft)_z5WEv7Q z%6SdQ99i4jzaV}qukASiug=D6ci)0|J-!JVL~lk27@T|YL{K1}WE$S>;~Zh=Yh7@o zYDr@due!i6?;PB&Fd3*D@mH#ehHXBdL^V{HBhQmPH)_{v%dviz0D<1b2AC$U`2APe zQ4@BuZssjQE(>hGfY!I32`AxzT{}o|SKwDV#3G>Q!3%SA%$01O2Rw13(r{2!=>-UW z(?Or_1r_HI5O7dV-59<$eCy<$Gq=yI$mtCtbRAkt^)7ba?7UUJQ@dSTNe!+`;f}Z; zfL0)|SUn)JFj<5moo-zP8ID&tNTzXj+h`Q|Ig$=#t33fKN0ck?&MFfX<;r`r>98A_ zv{_N(TmG|dIHna=NIFJKY%)%*o(?`9Tuq)@ zj-7hhRSdT0>Q^xFu>PN}LRj$3wgFNsi?*>8glbl(2@o2g`sNU$8mEe;7?f*zo*Ig7 zmnw=qsqnn%0OPfx4D^ByRn-fc<3LE73A5D?nyI4~Y>RG79S9m{js{5`eH#^OZG0vFPBd=9C4P!bZ$|(^4+k zY{tn`%CQDA%8+JRHV+ix@RlzXZAKvpG)n$c4d(}HYbJt&a4$qO_c_FIaGwz}cTB6l#r;F;ez#R+h*DhHNlkQ;z?2OGg0S&tDp zwcOc%SG+IZlb4l`9*sWDJEt9fVF+B52aV z#dA?Bl(%({9X^jgKMwwbK-1W}6}5Ee#Rv#re23>H@PEP5id0qIxT+Ryqg=qbtg08v zTESoOvYB;(z8fns`2AqK;^i*e12VQB33hlkfaDD%7z{V!P!3sMCtfS^@|Yn+9uZ;U zOahrF&lBBqr#D4W>R(TgNaD|sARX8Y!)zUA8!=IeZ^(jlTG)t%rQI8H6okE^bRf`% zS)h$FnMC5>j9(qcQx2khmpAiGz^`Z1f^Wt9XbQsPS6J+*@BMLh7-X1E4*r&`hXq0S OD|SRUxIut;8~y=jo>3J5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/comments/__pycache__/shape_writer.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/comments/__pycache__/shape_writer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e03bd02cc8952865e128e59bda5813cd473ccaac GIT binary patch literal 4885 zcmb7IO>7&-72f6UlFJ{7lBhpBl1y5bWV-sZEX4^WyKyBeiR~zD71s?Thgfk|*2+sR zv%8d~H5u^W1C2I_f*!0x4k}<23M`;1V4wlgLka}wp%)TT+Qn9f6!j%HC2|lTr@omb zDUop+bO64cdGqG)&HMR=f3K_aP*8+FTwnZmJw^QoH_C-ARSvE|G^V<*A-1yrR1$JZ3W_rq9Q3N=weJ)VtP6yi$-T!O-8i%qL>i0frJ!S z6-`;t2jWU1vYe2Oz8~&Z78azq7_mP_?~e+KD{)bd+xxdEU1}T*L*)S_Qc)UFQ3s-< z401$S_;HAVV}c@pf+~RWSP@b8sw3>Oyt9i!O1z;;x~Li|SrX&AHiraVh)Ic*qQV~Mmc``q+%;)_PJ=BE zq=fiw;g+b)DJe0TT3wNc%Bu}&_+YU+p@fjKSbXIceb%U} zjL}z9qUDf~<&CWjLy74l!y}fPxT7W+qTwAm`~2{5KcV*2T1vMVEXAe-ebG3U=$Gwo z)fScQ&x&Yx$TGUB+!ihOk|HHFeN`4ME`hz`J0ADqDJ=gjRX`GU25ei(ZHv~wBgcv> z$t2h+*(9q%EzGF+`Yqme?WAUL5DJo7m{q-)&#H=|TRz)HZGBiCyM-sw@L=qVDmFQ* zML;N4GVBN^5*ikRtStgECvgs1jhOlX=u;JDV8>AdHuk8%grBI}tgv3TO# z_U%v47sjsc^4IoY#fTZeD+PK?SWE-5#TT20w|n;)x;gR<$GFE;$O2RxT&hxVow(tL zP^of5=26Kd=fD}W&a5lrM6}U{>ls(6=F&@UNKqN!X4nk(sN||yKEp3@m31l=w(0z<&ZuF1g z*e2BYJ^L^^|EKxje4_mV2$)WwcO$(M7`V^pnf$EDd-Lz$YNfK*(6z2@Om4Prx9l{W z&vRe!b?>|HyVp*w*KY=j?ftv_fXVyb_ulueUH+UuZeM66TEY@M{K$o_fwrnH6yj=G z<(l{K;*g`P<}3{t@vJLj^oq%liz^vM){${cQ8(d2vJ8yG0l%hXDn>+8zinahMPrw( zDG;@vJwKaabB!5lsjg-KG&6L0*AP+t<$jQDDAy0ah%28Pc6*khh(U7|v!<4?N!1j{ zzZ^E{rRJIrXacwO``kw*&A~~}v6PN;ASs7Cou$Ig8OyaGC6OS@7PA6?=0qhbzx5Ih zL>KzHj|Anun?|rAfVD-;{%Lg*owOjAdR(y>QsTg7AZb}VkQmN?Dz<5I8@Bc*p!pF+CMH2f#kwQ}8?@F3 zmz*>m9GaWITZsl5D(R0?-HN8@BU zdREPF;{TYT5`U{^2>#d%87D-+(2S8zDe&l!lw?Gh*AzLei{rtBpx%;_1G2cFN5)

{{Cr2_EhK${R^1DdECUEoRKwN107Wd}XMnS!4xSF-R7mTJ4YWyAGzhfC z<18l`IZ}ecivj{j!OhF?yiz;BEa2@1*aPMUL_4p=)2fKn%fwebHzU{-)MgHW*^uC*`bLK7s+^%b0yZW%F*xa|- zvf~@dU4FvW=hJIT566nFr%gx+;e!9vQ-@L$Zmj7Q#C=Qdo0aHMcze3zZr zYwB3PUN|-S_)hWEMYHS7=5(R+97qSoa#ykR-9pFEqfC-bcY?oGB1pOJoyPv_^)ociXB5c?C>r-wl{w9wQ81_8?qE~JyhLN(h2@a+>UVbxc}(z+yT1g#TrVjIjX79{zOT;e2d z;)jZjw)qJ=vtCr^fQOTohQSRyYH0dfCrdlNqJVtkqv)Y8_`V!xdPj4-=^4qnzI9H} QU0+c^4&J3hbR(JczZuu6v;Y7A literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/comments/author.py b/venv/Lib/site-packages/openpyxl/comments/author.py new file mode 100644 index 0000000..9155fa5 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/comments/author.py @@ -0,0 +1,21 @@ +# Copyright (c) 2010-2024 openpyxl + + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Sequence, + Alias +) + + +class AuthorList(Serialisable): + + tagname = "authors" + + author = Sequence(expected_type=str) + authors = Alias("author") + + def __init__(self, + author=(), + ): + self.author = author diff --git a/venv/Lib/site-packages/openpyxl/comments/comment_sheet.py b/venv/Lib/site-packages/openpyxl/comments/comment_sheet.py new file mode 100644 index 0000000..67dccc5 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/comments/comment_sheet.py @@ -0,0 +1,211 @@ +# Copyright (c) 2010-2024 openpyxl + +## Incomplete! +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Integer, + Set, + String, + Bool, +) +from openpyxl.descriptors.excel import Guid, ExtensionList +from openpyxl.descriptors.sequence import NestedSequence + +from openpyxl.utils.indexed_list import IndexedList +from openpyxl.xml.constants import SHEET_MAIN_NS + +from openpyxl.cell.text import Text +from .author import AuthorList +from .comments import Comment +from .shape_writer import ShapeWriter + + +class Properties(Serialisable): + + locked = Bool(allow_none=True) + defaultSize = Bool(allow_none=True) + _print = Bool(allow_none=True) + disabled = Bool(allow_none=True) + uiObject = Bool(allow_none=True) + autoFill = Bool(allow_none=True) + autoLine = Bool(allow_none=True) + altText = String(allow_none=True) + textHAlign = Set(values=(['left', 'center', 'right', 'justify', 'distributed'])) + textVAlign = Set(values=(['top', 'center', 'bottom', 'justify', 'distributed'])) + lockText = Bool(allow_none=True) + justLastX = Bool(allow_none=True) + autoScale = Bool(allow_none=True) + rowHidden = Bool(allow_none=True) + colHidden = Bool(allow_none=True) + # anchor = Typed(expected_type=ObjectAnchor, ) + + __elements__ = ('anchor',) + + def __init__(self, + locked=None, + defaultSize=None, + _print=None, + disabled=None, + uiObject=None, + autoFill=None, + autoLine=None, + altText=None, + textHAlign=None, + textVAlign=None, + lockText=None, + justLastX=None, + autoScale=None, + rowHidden=None, + colHidden=None, + anchor=None, + ): + self.locked = locked + self.defaultSize = defaultSize + self._print = _print + self.disabled = disabled + self.uiObject = uiObject + self.autoFill = autoFill + self.autoLine = autoLine + self.altText = altText + self.textHAlign = textHAlign + self.textVAlign = textVAlign + self.lockText = lockText + self.justLastX = justLastX + self.autoScale = autoScale + self.rowHidden = rowHidden + self.colHidden = colHidden + self.anchor = anchor + + +class CommentRecord(Serialisable): + + tagname = "comment" + + ref = String() + authorId = Integer() + guid = Guid(allow_none=True) + shapeId = Integer(allow_none=True) + text = Typed(expected_type=Text) + commentPr = Typed(expected_type=Properties, allow_none=True) + author = String(allow_none=True) + + __elements__ = ('text', 'commentPr') + __attrs__ = ('ref', 'authorId', 'guid', 'shapeId') + + def __init__(self, + ref="", + authorId=0, + guid=None, + shapeId=0, + text=None, + commentPr=None, + author=None, + height=79, + width=144 + ): + self.ref = ref + self.authorId = authorId + self.guid = guid + self.shapeId = shapeId + if text is None: + text = Text() + self.text = text + self.commentPr = commentPr + self.author = author + self.height = height + self.width = width + + + @classmethod + def from_cell(cls, cell): + """ + Class method to convert cell comment + """ + comment = cell._comment + ref = cell.coordinate + self = cls(ref=ref, author=comment.author) + self.text.t = comment.content + self.height = comment.height + self.width = comment.width + return self + + + @property + def content(self): + """ + Remove all inline formatting and stuff + """ + return self.text.content + + +class CommentSheet(Serialisable): + + tagname = "comments" + + authors = Typed(expected_type=AuthorList) + commentList = NestedSequence(expected_type=CommentRecord, count=0) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + _id = None + _path = "/xl/comments/comment{0}.xml" + mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" + _rel_type = "comments" + _rel_id = None + + __elements__ = ('authors', 'commentList') + + def __init__(self, + authors=None, + commentList=None, + extLst=None, + ): + self.authors = authors + self.commentList = commentList + + + def to_tree(self): + tree = super().to_tree() + tree.set("xmlns", SHEET_MAIN_NS) + return tree + + + @property + def comments(self): + """ + Return a dictionary of comments keyed by coord + """ + authors = self.authors.author + + for c in self.commentList: + yield c.ref, Comment(c.content, authors[c.authorId], c.height, c.width) + + + @classmethod + def from_comments(cls, comments): + """ + Create a comment sheet from a list of comments for a particular worksheet + """ + authors = IndexedList() + + # dedupe authors and get indexes + for comment in comments: + comment.authorId = authors.add(comment.author) + + return cls(authors=AuthorList(authors), commentList=comments) + + + def write_shapes(self, vml=None): + """ + Create the VML for comments + """ + sw = ShapeWriter(self.comments) + return sw.write(vml) + + + @property + def path(self): + """ + Return path within the archive + """ + return self._path.format(self._id) diff --git a/venv/Lib/site-packages/openpyxl/comments/comments.py b/venv/Lib/site-packages/openpyxl/comments/comments.py new file mode 100644 index 0000000..192bbc4 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/comments/comments.py @@ -0,0 +1,62 @@ +# Copyright (c) 2010-2024 openpyxl + + +class Comment: + + _parent = None + + def __init__(self, text, author, height=79, width=144): + self.content = text + self.author = author + self.height = height + self.width = width + + + @property + def parent(self): + return self._parent + + + def __eq__(self, other): + return ( + self.content == other.content + and self.author == other.author + ) + + def __repr__(self): + return "Comment: {0} by {1}".format(self.content, self.author) + + + def __copy__(self): + """Create a detached copy of this comment.""" + clone = self.__class__(self.content, self.author, self.height, self.width) + return clone + + + def bind(self, cell): + """ + Bind comment to a particular cell + """ + if cell is not None and self._parent is not None and self._parent != cell: + fmt = "Comment already assigned to {0} in worksheet {1}. Cannot assign a comment to more than one cell" + raise AttributeError(fmt.format(cell.coordinate, cell.parent.title)) + self._parent = cell + + + def unbind(self): + """ + Unbind a comment from a cell + """ + self._parent = None + + + @property + def text(self): + """ + Any comment text stripped of all formatting. + """ + return self.content + + @text.setter + def text(self, value): + self.content = value diff --git a/venv/Lib/site-packages/openpyxl/comments/shape_writer.py b/venv/Lib/site-packages/openpyxl/comments/shape_writer.py new file mode 100644 index 0000000..cebfbc3 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/comments/shape_writer.py @@ -0,0 +1,112 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.xml.functions import ( + Element, + SubElement, + tostring, +) + +from openpyxl.utils import coordinate_to_tuple + +vmlns = "urn:schemas-microsoft-com:vml" +officens = "urn:schemas-microsoft-com:office:office" +excelns = "urn:schemas-microsoft-com:office:excel" + + +class ShapeWriter: + """ + Create VML for comments + """ + + vml = None + vml_path = None + + + def __init__(self, comments): + self.comments = comments + + + def add_comment_shapetype(self, root): + shape_layout = SubElement(root, "{%s}shapelayout" % officens, + {"{%s}ext" % vmlns: "edit"}) + SubElement(shape_layout, + "{%s}idmap" % officens, + {"{%s}ext" % vmlns: "edit", "data": "1"}) + shape_type = SubElement(root, + "{%s}shapetype" % vmlns, + {"id": "_x0000_t202", + "coordsize": "21600,21600", + "{%s}spt" % officens: "202", + "path": "m,l,21600r21600,l21600,xe"}) + SubElement(shape_type, "{%s}stroke" % vmlns, {"joinstyle": "miter"}) + SubElement(shape_type, + "{%s}path" % vmlns, + {"gradientshapeok": "t", + "{%s}connecttype" % officens: "rect"}) + + + def add_comment_shape(self, root, idx, coord, height, width): + row, col = coordinate_to_tuple(coord) + row -= 1 + col -= 1 + shape = _shape_factory(row, col, height, width) + + shape.set('id', "_x0000_s%04d" % idx) + root.append(shape) + + + def write(self, root): + + if not hasattr(root, "findall"): + root = Element("xml") + + # Remove any existing comment shapes + comments = root.findall("{%s}shape[@type='#_x0000_t202']" % vmlns) + for c in comments: + root.remove(c) + + # check whether comments shape type already exists + shape_types = root.find("{%s}shapetype[@id='_x0000_t202']" % vmlns) + if shape_types is None: + self.add_comment_shapetype(root) + + for idx, (coord, comment) in enumerate(self.comments, 1026): + self.add_comment_shape(root, idx, coord, comment.height, comment.width) + + return tostring(root) + + +def _shape_factory(row, column, height, width): + style = ("position:absolute; " + "margin-left:59.25pt;" + "margin-top:1.5pt;" + "width:{width}px;" + "height:{height}px;" + "z-index:1;" + "visibility:hidden").format(height=height, + width=width) + attrs = { + "type": "#_x0000_t202", + "style": style, + "fillcolor": "#ffffe1", + "{%s}insetmode" % officens: "auto" + } + shape = Element("{%s}shape" % vmlns, attrs) + + SubElement(shape, "{%s}fill" % vmlns, + {"color2": "#ffffe1"}) + SubElement(shape, "{%s}shadow" % vmlns, + {"color": "black", "obscured": "t"}) + SubElement(shape, "{%s}path" % vmlns, + {"{%s}connecttype" % officens: "none"}) + textbox = SubElement(shape, "{%s}textbox" % vmlns, + {"style": "mso-direction-alt:auto"}) + SubElement(textbox, "div", {"style": "text-align:left"}) + client_data = SubElement(shape, "{%s}ClientData" % excelns, + {"ObjectType": "Note"}) + SubElement(client_data, "{%s}MoveWithCells" % excelns) + SubElement(client_data, "{%s}SizeWithCells" % excelns) + SubElement(client_data, "{%s}AutoFill" % excelns).text = "False" + SubElement(client_data, "{%s}Row" % excelns).text = str(row) + SubElement(client_data, "{%s}Column" % excelns).text = str(column) + return shape diff --git a/venv/Lib/site-packages/openpyxl/compat/__init__.py b/venv/Lib/site-packages/openpyxl/compat/__init__.py new file mode 100644 index 0000000..dac0909 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/compat/__init__.py @@ -0,0 +1,54 @@ +# Copyright (c) 2010-2024 openpyxl + +from .numbers import NUMERIC_TYPES +from .strings import safe_string + +import warnings +from functools import wraps +import inspect + + +class DummyCode: + + pass + + +# from https://github.com/tantale/deprecated/blob/master/deprecated/__init__.py +# with an enhancement to update docstrings of deprecated functions +string_types = (type(b''), type(u'')) +def deprecated(reason): + + if isinstance(reason, string_types): + + def decorator(func1): + + if inspect.isclass(func1): + fmt1 = "Call to deprecated class {name} ({reason})." + else: + fmt1 = "Call to deprecated function {name} ({reason})." + + @wraps(func1) + def new_func1(*args, **kwargs): + #warnings.simplefilter('default', DeprecationWarning) + warnings.warn( + fmt1.format(name=func1.__name__, reason=reason), + category=DeprecationWarning, + stacklevel=2 + ) + return func1(*args, **kwargs) + + # Enhance docstring with a deprecation note + deprecationNote = "\n\n.. note::\n Deprecated: " + reason + if new_func1.__doc__: + new_func1.__doc__ += deprecationNote + else: + new_func1.__doc__ = deprecationNote + return new_func1 + + return decorator + + elif inspect.isclass(reason) or inspect.isfunction(reason): + raise TypeError("Reason for deprecation must be supplied") + + else: + raise TypeError(repr(type(reason))) diff --git a/venv/Lib/site-packages/openpyxl/compat/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/compat/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43dc30061579e9351581fabbde32da34ea3b83ef GIT binary patch literal 2168 zcmah~U2M}<6u#GX5+`k%6bcC&rS70GuQb5K(5M(M8l*}gix8_p_9<2sXXj)k9(Z7my~v+@<2kOFT526w27zPYsU$oN;{H|&pr2? zV}Ix8-ao?O5FjM~IP&#}egK}(g-2XNsAD3`0t67$Kpv(cq%xy1c{a@wnMIt&r8)BU zX}-Ka?QiG;=>P+c1LU6qC@{~s(b7Bv)F9&Lp}TfgL2s31(jgR@0_nCAC$>GMHX^jc zsgci*p87N?4S#j==nzq~nQ~T@Obh4qvrlQ96jA!lW4T}|ZdjK$z5(j(WIYR1kcJ4P znGzHkJ9wm+&zF)0Qd1&p^OB^?c~z3^kR;^|RMe>4E=k`MWzF6B8PsXim!rwS%!sLC zGc#-;lo&de%p_$~k&${58)K?snHeNovXsjg3~Z@5Gp_36na^^g88c_80|i+*C!bZ# zj8RbaLg|9GOEK~V+1e#ZIX!1dQle18Jo%8r+K6EK2%7?rIUa{Sy(8H`@emR{2#|** zPyH{#t`NLdbGHhtM*actDuDyjAPW(k;wNAQ4grgP#-TCN32#yrcr`LNykbdz^bKlR z;x>!^ze9-e{4c|n)}nwMvLc?;^7lNv_hl%usn;OW7F|!C`tO9@gjc{7_Ep$pP0(I& z09xTOi{MpOXApChZ9!`7PqWitn#;0?o#N*k0VW{gs$7|@CYTCbD^WOBffv@?sW4>% zS79VtB!_6)D@j1_HgO<0tjeyHi7Iywdd+4v8wD}<*!e~V zAYee1t$-Y;z`O7}k`0kdk=f)ZM%(Wqd`gQ*lswJCSp%2skZF-2($sNP6MZ&+UdB2( z2uz!!lI_nLI4@f`NZjmoM;iGfsrb^hBQBhbiMjtAv8Qg?ytT*n(TwfEUBt^7I6;`4 zoWvb8NKjYLOU`zAcdH(W1Dc`8nt3pRRK>uuW#E>o>9K{z`-rfAC&6<+=-f0Lz8+rg ziqD?7eqwIqr_(>2{`J_*iN&tu!|q+nJ;I9s*SYRl2*kT@p;~NUF1rvLs6_{yaW8KU zg%SxtH!O82uVze zM8xz*TjT zZY8{K=7VoDFPK0$QD;HNTdP!B?E*cA;BVU(wtO=E#d0M6AR^q42+Pq;52C&IqrG#| zLUiw+(cV=*=<2SuZ(e0V-`<(vQnYt@{bsUubF<@=GY$eNesgAM`{#?MC5)hQR1^2o9K1sqwecp%4i1yeqZk|5<}hg|o1@ku<75l> zQPi|W&j@a}gjz|$JBgm2Pv!_=qytt0oip3->|6@$c+SOw-K+0|=%yMUUkOI9^;COq zZCnZpcaJ~Vwr^qEzF)?dwjF%f5v#>NUhFtr;}4VWiNx=4cZTP--_9(?-&^eHukrm3 zda>OO=*9dfxs)&+Ej!@CGBG_Mah$4x4j#kMOs6Yctj;~tPi=NkMt>L6yV8m3!r>3N z*Wp3Dn{3b<#oSNWDhnZe;RkT*BOp8hkw@U|zd^@8eg+1g0m?c+=Z2Y~8^Q1Q&at=m Q*CKtB?R91=-06h=51A?d9RL6T literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/compat/__pycache__/abc.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/compat/__pycache__/abc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93cadf9d4813cefbda7cf214eade4a4fc3217383 GIT binary patch literal 375 zcmXv|Jxc>Y5S_Wbe49cM1?}PoUSZOU2zn?eDx#(^tjOke)o3nv?4J2()7jY>u+c^k ze~P7z9%y4_7fd6m+>1J}``)~H^LC%I*)-^4_r=p2jUQ3-U-3WE+tB11Qow;@62VN8P@#Yi`_PD%v906{nr<}p^_k^Cl<@Id<;&?E=YKr8kc$rgrWdBxU{(6A)} zCL{Z{6$=R~JA)?7th>G^gH>7rrW literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/compat/__pycache__/numbers.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/compat/__pycache__/numbers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b55f28c290299418447a39c949465bf27b1664cd GIT binary patch literal 1485 zcmZvb%}*0S9ENAQA8nB)wBkpk8b7EJqM%ri5JHTlL=qt=G^Wc!v+Yiyxb1FsTcDmW zUNzySM|+X@Pk7_xMNc;4#l(}h3NbO9{7t*#Kw^{b`@GM5Z71ocNTdtF$9SJvf2<<( zgBAX{=)>X1077q&iA-#vGS)CgBtRsBi;^aXnGaZsrkIkZ5_K256GSG;Mi1XcB-of} zoWS;S776yOXq>>F=PVNJ1<^QxjdK(Kvywo z!D&(`l?`itX=b3G2F*@$B^aersZym%(Xx#yjm&4}(obenxuxtvdXXxXTG^>n1?)nW zo|-K?wp&fRuI*CATL-3Ut&=irQlLt$9jxT2%nA)zc4duyX}I zdE2&fG}L|xIG+Y#K3OB~2Xx48?Z`+?=oyc=p1x$8=Fs9yN>3SH!7#~!Yj2Q3)zeL* zYUE1oTOqE#Nh+KAqf%b?N>y^pF$&L&HR9>ELn=;v+Zry|Wyh!v!=2_~*CDvr&}7** zYZjSu**^or*Ets)%%9_`&FZ=ZhdN$f;gs*Gdb0mM()_mmBtEd{_;+IO^kj?j2@fhZ};Cgv6Am| z@-_T3{P1`2-v(ssUSA^l3-z5zzL;xC@WcMJ!YFk50AUV>8OHAkh literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/compat/__pycache__/product.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/compat/__pycache__/product.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..240bb8e2d1971119534cbe497008fb1051617227 GIT binary patch literal 632 zcmX|8&ui2`6n>LrlkCPK?TS!(2`Fd|ZV&50q=T) zh<9%mLFi2s{}eBZ2TK$$p1jrWMS5~(+2+A}^SvK4?|W}PFD$e`34Xsla1p?7?VO7> z2h(*04uL=j1Q8=eA)1{=Xb|%igl1F6t<=gIVFSU$xB}F^3S41ohK(H+*@pvj2li3W zcy_IoVL9j&oDrWsEr(;A(p>txjQeZ;=0pxy?sq%4T7Pu+jYN^EMH4cWP9G|B2(r$N zjJl=<@|-@5>^fM3=kRHMXA1(f5m;4ox6BjCSSl);Q&J|ha#=w+mW)?sR;B@}T%j1# zJfT9j_RnzdcC;-h7ttd|NM~!k7xl16Frk~Ajc6i8M6ks1Fe@0Blt*KlkE8zZaU_P4 z-Y9Ugho4XpsXlozIY?I%mK9j8>gAM)>=cvAnPaa1Nvl{^<^}xpE`9e_zIrR~?jQBv z_CH+z=5@bV-Kk2dfhtR13!KV{W5SX+=6V}kFJkskW$91g7nEOl4`%G{anATh;GV8& z>V&(NDHV+qD?rUP;totAw|7#%fqdbz(hsc!fAycOK5%`Famx5gd zb|WWtM7mVLHQhFQ+=mMHi z{Lux=DcaO?oy~8?G#G=mR;C^?Y{Gf4{~qDg)LciqRr5+PN0?4-h zFmmq{Zga|bVbL|s?7|1RLXL2QnDiENSE%9ff=N80Tjh$&Jjx2|)LAclWGxlA<z&?Kk#Ir4QpiVSL+Ukp6 zUudbBz3HFSOy^v>q1;b&;T#P|u>dCm#X4FMMyJNsS+CcX2nFau8pr4YvIG0!{tJjj z!DL2eqcE`%5CU|A*tV`SL6-rHOk66P1o3>Cq3s!AdJzPa*%?o4Uu#}#jZYt>Uwv3? zr?cNHt@PC&q;~phWB!YqokVi`Zu4$SO|uukV}C^a(jjFE_dKTSW!GG@g&x!OPuGau zI~mb+(={L~fpn0EKhe8vgNk(bF^h{VM7v!NvlT7Cgb+pY6o_Z{&~K6wQIBF$Wa_CZ zN2U%Dh#--`@_*xQG)IgQH8&py6cGz(ms7OOl`Pu~2?rFbTDA>*1X3D|5|3&Qtq!=! z1v$MEEknbvgR!+7#1-^4fuGK6o$O@W=(6Az{gEmqtBfxD$xlGJL+mv=ZyDmTBCO`e^$YwADNLetUy8$BL9v;q~b;J_GPwMz3@LfQ|*!ci` zCe@{X@|y#{x^&FTDOiVy3F^%#Y+P)_K=`t|v=X+w$XGmeCpdZxN=VRYFyYrhgaqBW zvOD+XTzh<~lS~P1PiZGJtyt!9JlQO^3K|TEVaorn}R2>wbipX)q;1 zKo2>1Nb%4fa_}Tb{}fMR!LSw-)I%>4h+aH7o6WX}KG^s1dvD&G_nUo}Osc>Iz1i5& zA^>0gAQT=CWw6H0AsAo?7T8b$!S^GUU`HwuTdat~ShS>ygr(hKztPE&sVIhI$X3*j zRbsqWc>$GpLo7tk{Cq+1Vg_QEnKmv&JlUiUa(rVtTPtTmP?22Ocu-oqU#zY_UM-b% z9}Pv~j>x~k53UY@o#&ds!VTbfdBbImeY)ni&Uq{v+rXK9ea|<_aZF`dAI=B$^RG(+ckfUSbb3lALiO&)7 zN%i6;b%R!(NEzXeB?qm1>hix)@s74ZF`?SJYZwdVdqu5?sE!Q0O59znGpg~oMOD+T zxrAY&)v;68md#C#nhej^kp2X1W2(6|?9>`htwr6nYltoKQKqv^7itYJLHUN&03c~T z)u)I)=c)zYqM6QIclsoH{WOv8WM3|IZ@$iUmwJ=AcBwxBW0}@+KLy##NBH0&N5%sr z32Lf6-Am`%a$g-nKjWZIc1qpbC-G~&boMZHkou6G;b|pE%P>B5BzNgaa`rTRsZ)BT zw&h+T-C7>-Yd}E_xRN;GI~N3U!Wz^Yt8;ct*QxT~+4aOnr8O_gA7zuH0pb2iZ-HdE zAt|oB*plrUdltS+rg-S{OlP_3i-I8hQb4%!8Kysh`bCL7&-6`on{^53Q`k)~uhrUd;olwCS$n3wnZ@zgu``-KJAN%$N2{i2w7cQ55gnWfBZc`eA&0oS`iReV9Ir6DQaU|vF zlr#=wiM&j7&pgp(=2`VPE5>DeR)JYBlkfPN^NKz1hxxz`Ywv6@8Ty*S+9b8;00{qi zHa)}g8J20dV0UPNZL<}`5@BSV>SSEf={y9v%s!KQ>2%!+JY7#e)N6&ztA!?Q)Bz%4niO)*P0 zW{b@7scN2GRaIE!$>fCP17WL`OPXNtKE;g71zlM5b&FmR`1xIS``^Urlj#eBaglzl zpzEpgXHKV2Ya*lR?B~2N$ufpW>zbjd*{NcI8;qx~u>6(utJzCw0q*^t7cKoaOsq&ugvQ|0C6KIRNuw2*eFii*_!Zef#XYV>d?@ zh8L#mk&fl=-;LjmJYDNJRHDE2K2S)kcgss!qHmcu&E?bO_)6beyc#)C@t@cP1Ty-G zZ218f4n|e2psG$4^qCxv!>T$xqvafp?aL>G$6yJMqQC>O1%x~iDCWtgEGs7+8&vNd zd126ON8T(=N|x7&x6!1B$3e^6QFNd)DQ zM@9tp%!qaaPt0+o5Ud4)l9!GnZfs{?lJxE(cjCzl2#izO36cb zvaYyzyvJ1b#@b$MdLL)8SbXSWB0t@PY$hS90C2{Wa#Giijk#9v>`Pu!hpMIYBuRsp{&B1o4oT`fZ3n>2k z9ZIkdLU)M4IR}RrSdLAxyaATU7LJvXV>#lO_m*!0>My`pUabfWr*p)&l-GcCb^Ze! z?}M)Znq<0aGqGaK6m!h-X!%)78O~)jVR-<<@(QF+-C-K!!eof=hmKL5 zo#wqb_Pd^0!RC+DIp#6PAh)Ev5O|-kncNW$o!MO5{-|?BRuVVihXUiav@R&M18oc5 zT3c+vUyH>Tf(;g4`W_3{qn*pc%hy*%s?ldl(m&f`wdj%i(Z2O)-v`s5UHWr(Wni$< z|H4LesNQyH`Pt>mE6PS&sun$joL=tUi1yZ^hnL3Q9xD&ujrP}Li8B4@`Hk4I@6SHB z5lhzNN0z5=zj^D;wZKOFWUamHcH~xMh2Cu+sCV>~hd&|W>b+Vw@%$W zRk~gc^;AMf>pf4e#6BEcc)9e-dbq3Jn_L;F_CB}ZtF&~j`@3tQR@>ODhI%WZW1zm% zzjkmnRqZ_iD_&g>H!Xf$4fR(-se1p>J7?COuO1t$_P+ooqwC=wxYFE@bgxIc%RS|* zYs%WyYUIU=|3#bfM>*EU-IoN+b&di{wZQ1an@NxI5_Rqgs2WZBEEz9)mR~gP$#$G_ zq#Y;Xuz1)oyYMalpmRqW;&=zcEEiY;9(X9FaMhyGe~}|wUN1daif$3;wpt|`C|&!8 SK(`g_qc72t@eRS=_UAjZoRR+k literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/base.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad943d6e02a7ef69f1d3becf6784d1b69125cfaa GIT binary patch literal 13241 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/container.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/container.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b927a72e0aee36a294d7ebac86f3ca893da7e1c GIT binary patch literal 2072 zcma)7&2Jk;6rb5$JC5T`R3{A$ZPQIZP+cHZ+9D(<2xwANDMW>|2w84d%kHFcSnn<~ z<1{vo6jedEqKI-p{SqoCM3hVU4=TX{iHoCB1(qB@aN*`OR1{9U*$>MpMdC?*``*l( zkKgaTdHzmS(+I@);`DSyM(9`J#FB`NjRRm@K^Dp*3tN(nOHy9KNJ6h7OI}2lLgZyw zD_ zh)qhw;py~A>dqD|B0`Dg5R))w(2Dl*$rG@nMu}l*hGS{xX^|7{t=GoWzl&?+u-`Ej zZea>P7AZ0|PJ!_OU?M1w0hdH%3ooMOXgUvwEUC>;kfcD`n(wfbMU+p~(G<24i>Z8P z9nIl426Y8-(4kzwOL$@l`@It`KT-0+dlPGnQkTN8 z!iYV^#A@yD>0{3oPBWmcaLTo;;mPC23dam)8WsVfW{AmI!7{j^7fYT?IiZDF;>;Gt zi*FYg5cITXnC}?p2rIZAalFc$eGsTMY0={@Wd~b{8TKlE2RF_+Mu}8=+wcrWgFSGW zjTEQ_^jr5(BQ>-kko;e?v;%^vSWZRph0tgQOkX8)9-ttWE-Ilq(0=x&sXnn<5J|;d z%s8=Nqa^$So^3F$pc)=UA4{fm4x-NNL}*^Bp&1ePkjz9S+&)~BmZJ=QB3;_0pm}*- zl28rR=72)_2v3+ba1!6Ri05SA)blb zLl_k3nlvMF`;f%XCf*05OM4W^%VfluLd9jM3d&C!9+aj9<>!Xv$+Sz1ceaX?_JhyF ziWYs3gY!_GhO2jp&?BH0&|2U2tD`r^uZ`d7%hfx7%J$b^`607)HM3(Sv*YR;H}lu> zHwt$%2bwbKeeCC+ZH?5ne^-_$*?_m}V0?-9X2C^jH;;)8d zzF=JbED?JbFcH83p=U> zttwq)MTc?2F-cUkr{L8EeFv%)Oh3WO9-&keVJ^xNqdQ1D7nVjk}M zCUObCL)R_W1XTTT*B+iL*~3$1$K*xVVZrP174c6StXT?sV%ShqM?+Fxq{DDcfq`uY d)s!*D>q!MG_cI7T`A2dm9=yEwK7vnh_&?_!;VJ+C literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/excel.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/excel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a796b9f2de700f506ec32cc94a308edb53bd0d3f GIT binary patch literal 4286 zcmb7H>u(g-6~D7HyF2^v6TdKzY+3_57@KDxMI(|v zcUen|WT{3`Bu7<6BvQ$hswxQng-ZS2FGNrYjfg~5RcgLD@>vzvRzcYVnYfBO+`X8^{v=fB<9Y4Yn-Keae5(v3ROrjD~FeA2*kEjs=>!K~@ zB~{{e$&Th@Y7FX8GiJy0vMT2jY9gOhllhdI%BR&dZ;RV)`F6EkAQ5tonDP=a6I6aE z26L$$T$==Ks!7|)wQ10{(L}?xizd}>-qH>&9ZfCUxV96tU9`Pn-@~=tpxxG_?d94Y z(Du?)!?urW`#{^@w2pqR9RTh2ChY*%4uW<^lXkng+uXGzsDtI5${UrP$%zGn+8MV< z4QtLaGA4BmW)-~xbCX}=<`uz@U7EP4P0c_pl-kI${c{SdJ*7pLm}xoUt68l`Cym4~_gpADMe^GnoTycjI>0a?d+{%ww*%w2IQb90vqra3xuc04z(yM}Jk zX;!#J4bRP)x~FSazF1(e!`wV|=5rUV>p9o*=txmFeyQJ}Zmv+IPO-dTA8f+%AVru* zi)GdhQ*qG?6*mrIiM(jvb>|#I1#fvR7&@;w);ug)wkW+ zGjuA}g`yjTAJ;UqV1SE=FuUJI7vMg4)YQCkk@{lZazN+{t#Bbq48xbAl-?$!ctwEC_0R z2CrIjnlb~n4<1+9o6R0RbV#XY`FV3OrYPb0Z+wsKvHtw0wI8h0XF7->@>v6c;S|5u zS3&$%xJSJ3=8d}93*maN46q~%(U>*)|od=cW3 zA7`{^>jq`$k$!Z}F6f>gbxTEvKXAw{^)wCQgXB_s&X*f~qw~65qJBct3|n_yFqEJ_ zIBAXXi-G4;>3)g%=*Cb-LGS()#P>DwJk`5GKc9J;dUMtI;>z#sXFc2RO@2DL`r}ph zq-X!~#Pgp1&!eBw`{`Bh%Yor1JqJJ~x8053?f6Vy-SbyD%bnyE-(=fhc(xk_x*5Zz z_-z{tg`i@?h6HvHv@XJWI#}?VXo_M48xV}|G0vQ*oqLw-MyCYN{7#ah${GO?xF?!# z?Vdx>^748|2o)cK28${sh$)&8V3cTCP$WMwvEWh1wF=IZ(QqCx#5#8~yl?mLV2K8` zpp?l2VG7tlEHO)oumhlF$3eK*E0f_{!kBJB0MN8bcViAXhd}o(7_O&4)W}+l^z<)F zpUA{-;$jlXKUjydf#AO6r=sY@MyIO zG~6VX^(=_Zpi$|O5PG{B1>htOT&yg@jc#jf>Z0X(iokY3|JQ+#@tp#Q5NAUWPr(?? zAoAT-`Zi6~!0>%AW^bcFMu79+uqg3X>=0&-4#VNM1Q2m!DDZB$c!dza?$zy2lfwaq z15FsB;U)~xk+H1fxxB=XiVzXe(UAY;OVrjq@UzQPuO2TRf}cR5cY&9wpVV!;@GH$J zIJEVw(Q_DzDR|s82)HPneYNw?x_a+i2o4#Ww_f0XNlwydbeA4KwvnGqU(1f2y!zgV zs*hBFn}-k1-afXd?0-dhWbvJMs+;YOF1Bi*=g`*deFj#^P+W$m!QQ_J*&AD4YZKDB zl4VxLZX<(WYIXbV#gRt+*#A*Kd}J}Vxb<4mFBpoSH?MU%Tr0M0S}O(uEbDtgY{itE zB}HIK;7ef17_cM+qj89jmvje6a`xKQq1mzQ2D-Di4<9(XsBl%z99FU?|5xjnGB#Ab zwyA4)oWVdtmkso|ut-qB@AV5HkW#CWJDot6p<9P`@DAfBkYBjPfc$_iTgflD;G!Qb z6@ku}0^Kj9YsV^p;WR5&d9epevZKARrYzK7n z`@-Lh(S^J{Y7}@D2wZ|1b=qMRL4QU?%*J!JiQ(5&=PQ9^ercPm*7F?idU)Xo zuT-&qyq=VWu9aAwz-z6KwD;DM^;l9+R{H7$UiHDa(2w2VRqw(2#f`cs^exZV3B2m* jh@cBAr*J%7z`;KhmigC*@RfkEpg+9o12N$kKd1iyWD%>y literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/namespace.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/descriptors/__pycache__/namespace.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70cd9927b97c4853e07ae6ca13ce25f79c6f2c64 GIT binary patch literal 505 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 self.max: + raise ValueError('Max value is {0}'.format(self.max)) + super().__set__(instance, value) + + +class Min(Convertible): + """Values must be greater than a `min` value""" + + expected_type = float + allow_none = False + + def __init__(self, **kw): + if 'min' not in kw and not hasattr(self, 'min'): + raise TypeError('missing min value') + super().__init__(**kw) + + def __set__(self, instance, value): + if ((self.allow_none and value is not None) + or not self.allow_none): + value = _convert(self.expected_type, value) + if value < self.min: + raise ValueError('Min value is {0}'.format(self.min)) + super().__set__(instance, value) + + +class MinMax(Min, Max): + """Values must be greater than `min` value and less than a `max` one""" + pass + + +class Set(Descriptor): + """Value can only be from a set of know values""" + + def __init__(self, name=None, **kw): + if not 'values' in kw: + raise TypeError("missing set of values") + kw['values'] = set(kw['values']) + super().__init__(name, **kw) + self.__doc__ = "Value must be one of {0}".format(self.values) + + def __set__(self, instance, value): + if value not in self.values: + raise ValueError(self.__doc__) + super().__set__(instance, value) + + +class NoneSet(Set): + + """'none' will be treated as None""" + + def __init__(self, name=None, **kw): + super().__init__(name, **kw) + self.values.add(None) + + def __set__(self, instance, value): + if value == 'none': + value = None + super().__set__(instance, value) + + +class Integer(Convertible): + + expected_type = int + + +class Float(Convertible): + + expected_type = float + + +class Bool(Convertible): + + expected_type = bool + + def __set__(self, instance, value): + if isinstance(value, str): + if value in ('false', 'f', '0'): + value = False + super().__set__(instance, value) + + +class String(Typed): + + expected_type = str + + +class Text(String, Convertible): + + pass + + +class ASCII(Typed): + + expected_type = bytes + + +class Tuple(Typed): + + expected_type = tuple + + +class Length(Descriptor): + + def __init__(self, name=None, **kw): + if "length" not in kw: + raise TypeError("value length must be supplied") + super().__init__(**kw) + + + def __set__(self, instance, value): + if len(value) != self.length: + raise ValueError("Value must be length {0}".format(self.length)) + super().__set__(instance, value) + + +class Default(Typed): + """ + When called returns an instance of the expected type. + Additional default values can be passed in to the descriptor + """ + + def __init__(self, name=None, **kw): + if "defaults" not in kw: + kw['defaults'] = {} + super().__init__(**kw) + + def __call__(self): + return self.expected_type() + + +class Alias(Descriptor): + """ + Aliases can be used when either the desired attribute name is not allowed + or confusing in Python (eg. "type") or a more descriptive name is desired + (eg. "underline" for "u") + """ + + def __init__(self, alias): + self.alias = alias + + def __set__(self, instance, value): + setattr(instance, self.alias, value) + + def __get__(self, instance, cls): + return getattr(instance, self.alias) + + +class MatchPattern(Descriptor): + """Values must match a regex pattern """ + allow_none = False + + def __init__(self, name=None, **kw): + if 'pattern' not in kw and not hasattr(self, 'pattern'): + raise TypeError('missing pattern value') + + super().__init__(name, **kw) + self.test_pattern = re.compile(self.pattern, re.VERBOSE) + + + def __set__(self, instance, value): + + if value is None and not self.allow_none: + raise ValueError("Value must not be none") + + if ((self.allow_none and value is not None) + or not self.allow_none): + if not self.test_pattern.match(value): + raise ValueError('Value does not match pattern {0}'.format(self.pattern)) + + super().__set__(instance, value) + + +class DateTime(Typed): + + expected_type = datetime.datetime + + def __set__(self, instance, value): + if value is not None and isinstance(value, str): + try: + value = from_ISO8601(value) + except ValueError: + raise ValueError("Value must be ISO datetime format") + super().__set__(instance, value) diff --git a/venv/Lib/site-packages/openpyxl/descriptors/container.py b/venv/Lib/site-packages/openpyxl/descriptors/container.py new file mode 100644 index 0000000..4b1839f --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/container.py @@ -0,0 +1,41 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Utility list for top level containers that contain one type of element + +Provides the necessary API to read and write XML +""" + +from openpyxl.xml.functions import Element + + +class ElementList(list): + + + @property + def tagname(self): + raise NotImplementedError + + + @property + def expected_type(self): + raise NotImplementedError + + + @classmethod + def from_tree(cls, tree): + l = [cls.expected_type.from_tree(el) for el in tree] + return cls(l) + + + def to_tree(self): + container = Element(self.tagname) + for el in self: + container.append(el.to_tree()) + return container + + + def append(self, value): + if not isinstance(value, self.expected_type): + raise TypeError(f"Value must of type {self.expected_type} {type(value)} provided") + super().append(value) diff --git a/venv/Lib/site-packages/openpyxl/descriptors/excel.py b/venv/Lib/site-packages/openpyxl/descriptors/excel.py new file mode 100644 index 0000000..d8aa202 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/excel.py @@ -0,0 +1,112 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Excel specific descriptors +""" + +from openpyxl.xml.constants import REL_NS +from openpyxl.compat import safe_string +from openpyxl.xml.functions import Element + +from . import ( + MatchPattern, + MinMax, + Integer, + String, + Sequence, +) +from .serialisable import Serialisable + + +class HexBinary(MatchPattern): + + pattern = "[0-9a-fA-F]+$" + + +class UniversalMeasure(MatchPattern): + + pattern = r"[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)" + + +class TextPoint(MinMax): + """ + Size in hundredths of points. + In theory other units of measurement can be used but these are unbounded + """ + expected_type = int + + min = -400000 + max = 400000 + + +Coordinate = Integer + + +class Percentage(MinMax): + + pattern = r"((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" # strict + min = -1000000 + max = 1000000 + + def __set__(self, instance, value): + if isinstance(value, str) and "%" in value: + value = value.replace("%", "") + value = int(float(value) * 1000) + super().__set__(instance, value) + + +class Extension(Serialisable): + + uri = String() + + def __init__(self, + uri=None, + ): + self.uri = uri + + +class ExtensionList(Serialisable): + + ext = Sequence(expected_type=Extension) + + def __init__(self, + ext=(), + ): + self.ext = ext + + +class Relation(String): + + namespace = REL_NS + allow_none = True + + +class Base64Binary(MatchPattern): + # http://www.w3.org/TR/xmlschema11-2/#nt-Base64Binary + pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$" + + +class Guid(MatchPattern): + # https://msdn.microsoft.com/en-us/library/dd946381(v=office.12).aspx + pattern = r"{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}" + + +class CellRange(MatchPattern): + + pattern = r"^[$]?([A-Za-z]{1,3})[$]?(\d+)(:[$]?([A-Za-z]{1,3})[$]?(\d+)?)?$|^[A-Za-z]{1,3}:[A-Za-z]{1,3}$" + allow_none = True + + def __set__(self, instance, value): + + if value is not None: + value = value.upper() + super().__set__(instance, value) + + +def _explicit_none(tagname, value, namespace=None): + """ + Override serialisation because explicit none required + """ + if namespace is not None: + tagname = "{%s}%s" % (namespace, tagname) + return Element(tagname, val=safe_string(value)) diff --git a/venv/Lib/site-packages/openpyxl/descriptors/namespace.py b/venv/Lib/site-packages/openpyxl/descriptors/namespace.py new file mode 100644 index 0000000..93cc9e4 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/namespace.py @@ -0,0 +1,12 @@ +# Copyright (c) 2010-2024 openpyxl + + +def namespaced(obj, tagname, namespace=None): + """ + Utility to create a namespaced tag for an object + """ + + namespace = getattr(obj, "namespace", None) or namespace + if namespace is not None: + tagname = "{%s}%s" % (namespace, tagname) + return tagname diff --git a/venv/Lib/site-packages/openpyxl/descriptors/nested.py b/venv/Lib/site-packages/openpyxl/descriptors/nested.py new file mode 100644 index 0000000..bda63a2 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/nested.py @@ -0,0 +1,129 @@ +# Copyright (c) 2010-2024 openpyxl + +""" +Generic serialisable classes +""" +from .base import ( + Convertible, + Bool, + Descriptor, + NoneSet, + MinMax, + Set, + Float, + Integer, + String, + ) +from openpyxl.compat import safe_string +from openpyxl.xml.functions import Element, localname, whitespace + + +class Nested(Descriptor): + + nested = True + attribute = "val" + + def __set__(self, instance, value): + if hasattr(value, "tag"): + tag = localname(value) + if tag != self.name: + raise ValueError("Tag does not match attribute") + + value = self.from_tree(value) + super().__set__(instance, value) + + + def from_tree(self, node): + return node.get(self.attribute) + + + def to_tree(self, tagname=None, value=None, namespace=None): + namespace = getattr(self, "namespace", namespace) + if value is not None: + if namespace is not None: + tagname = "{%s}%s" % (namespace, tagname) + value = safe_string(value) + return Element(tagname, {self.attribute:value}) + + +class NestedValue(Nested, Convertible): + """ + Nested tag storing the value on the 'val' attribute + """ + pass + + +class NestedText(NestedValue): + """ + Represents any nested tag with the value as the contents of the tag + """ + + + def from_tree(self, node): + return node.text + + + def to_tree(self, tagname=None, value=None, namespace=None): + namespace = getattr(self, "namespace", namespace) + if value is not None: + if namespace is not None: + tagname = "{%s}%s" % (namespace, tagname) + el = Element(tagname) + el.text = safe_string(value) + whitespace(el) + return el + + +class NestedFloat(NestedValue, Float): + + pass + + +class NestedInteger(NestedValue, Integer): + + pass + + +class NestedString(NestedValue, String): + + pass + + +class NestedBool(NestedValue, Bool): + + + def from_tree(self, node): + return node.get("val", True) + + +class NestedNoneSet(Nested, NoneSet): + + pass + + +class NestedSet(Nested, Set): + + pass + + +class NestedMinMax(Nested, MinMax): + + pass + + +class EmptyTag(Nested, Bool): + + """ + Boolean if a tag exists or not. + """ + + def from_tree(self, node): + return True + + + def to_tree(self, tagname=None, value=None, namespace=None): + if value: + namespace = getattr(self, "namespace", namespace) + if namespace is not None: + tagname = "{%s}%s" % (namespace, tagname) + return Element(tagname) diff --git a/venv/Lib/site-packages/openpyxl/descriptors/sequence.py b/venv/Lib/site-packages/openpyxl/descriptors/sequence.py new file mode 100644 index 0000000..d77116b --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/sequence.py @@ -0,0 +1,136 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.compat import safe_string +from openpyxl.xml.functions import Element +from openpyxl.utils.indexed_list import IndexedList + +from .base import Descriptor, Alias, _convert +from .namespace import namespaced + + +class Sequence(Descriptor): + """ + A sequence (list or tuple) that may only contain objects of the declared + type + """ + + expected_type = type(None) + seq_types = (list, tuple) + idx_base = 0 + unique = False + container = list + + + def __set__(self, instance, seq): + if not isinstance(seq, self.seq_types): + raise TypeError("Value must be a sequence") + seq = self.container(_convert(self.expected_type, value) for value in seq) + if self.unique: + seq = IndexedList(seq) + + super().__set__(instance, seq) + + + def to_tree(self, tagname, obj, namespace=None): + """ + Convert the sequence represented by the descriptor to an XML element + """ + for idx, v in enumerate(obj, self.idx_base): + if hasattr(v, "to_tree"): + el = v.to_tree(tagname, idx) + else: + tagname = namespaced(obj, tagname, namespace) + el = Element(tagname) + el.text = safe_string(v) + yield el + + +class UniqueSequence(Sequence): + """ + Use a set to keep values unique + """ + seq_types = (list, tuple, set) + container = set + + +class ValueSequence(Sequence): + """ + A sequence of primitive types that are stored as a single attribute. + "val" is the default attribute + """ + + attribute = "val" + + + def to_tree(self, tagname, obj, namespace=None): + tagname = namespaced(self, tagname, namespace) + for v in obj: + yield Element(tagname, {self.attribute:safe_string(v)}) + + + def from_tree(self, node): + + return node.get(self.attribute) + + +class NestedSequence(Sequence): + """ + Wrap a sequence in an containing object + """ + + count = False + + def to_tree(self, tagname, obj, namespace=None): + tagname = namespaced(self, tagname, namespace) + container = Element(tagname) + if self.count: + container.set('count', str(len(obj))) + for v in obj: + container.append(v.to_tree()) + return container + + + def from_tree(self, node): + return [self.expected_type.from_tree(el) for el in node] + + +class MultiSequence(Sequence): + """ + Sequences can contain objects with different tags + """ + + def __set__(self, instance, seq): + if not isinstance(seq, (tuple, list)): + raise ValueError("Value must be a sequence") + seq = list(seq) + Descriptor.__set__(self, instance, seq) + + + def to_tree(self, tagname, obj, namespace=None): + """ + Convert the sequence represented by the descriptor to an XML element + """ + for v in obj: + el = v.to_tree(namespace=namespace) + yield el + + +class MultiSequencePart(Alias): + """ + Allow a multisequence to be built up from parts + + Excluded from the instance __elements__ or __attrs__ as is effectively an Alias + """ + + def __init__(self, expected_type, store): + self.expected_type = expected_type + self.store = store + + + def __set__(self, instance, value): + value = _convert(self.expected_type, value) + instance.__dict__[self.store].append(value) + + + def __get__(self, instance, cls): + return self diff --git a/venv/Lib/site-packages/openpyxl/descriptors/serialisable.py b/venv/Lib/site-packages/openpyxl/descriptors/serialisable.py new file mode 100644 index 0000000..1bc9ef0 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/serialisable.py @@ -0,0 +1,240 @@ +# Copyright (c) 2010-2024 openpyxl + +from copy import copy +from keyword import kwlist +KEYWORDS = frozenset(kwlist) + +from . import Descriptor +from . import MetaSerialisable +from .sequence import ( + Sequence, + NestedSequence, + MultiSequencePart, +) +from .namespace import namespaced + +from openpyxl.compat import safe_string +from openpyxl.xml.functions import ( + Element, + localname, +) + +seq_types = (list, tuple) + +class Serialisable(metaclass=MetaSerialisable): + """ + Objects can serialise to XML their attributes and child objects. + The following class attributes are created by the metaclass at runtime: + __attrs__ = attributes + __nested__ = single-valued child treated as an attribute + __elements__ = child elements + """ + + __attrs__ = None + __nested__ = None + __elements__ = None + __namespaced__ = None + + idx_base = 0 + + @property + def tagname(self): + raise(NotImplementedError) + + namespace = None + + @classmethod + def from_tree(cls, node): + """ + Create object from XML + """ + # strip known namespaces from attributes + attrib = dict(node.attrib) + for key, ns in cls.__namespaced__: + if ns in attrib: + attrib[key] = attrib[ns] + del attrib[ns] + + # strip attributes with unknown namespaces + for key in list(attrib): + if key.startswith('{'): + del attrib[key] + elif key in KEYWORDS: + attrib["_" + key] = attrib[key] + del attrib[key] + elif "-" in key: + n = key.replace("-", "_") + attrib[n] = attrib[key] + del attrib[key] + + if node.text and "attr_text" in cls.__attrs__: + attrib["attr_text"] = node.text + + for el in node: + tag = localname(el) + if tag in KEYWORDS: + tag = "_" + tag + desc = getattr(cls, tag, None) + if desc is None or isinstance(desc, property): + continue + + if hasattr(desc, 'from_tree'): + #descriptor manages conversion + obj = desc.from_tree(el) + else: + if hasattr(desc.expected_type, "from_tree"): + #complex type + obj = desc.expected_type.from_tree(el) + else: + #primitive + obj = el.text + + if isinstance(desc, NestedSequence): + attrib[tag] = obj + elif isinstance(desc, Sequence): + attrib.setdefault(tag, []) + attrib[tag].append(obj) + elif isinstance(desc, MultiSequencePart): + attrib.setdefault(desc.store, []) + attrib[desc.store].append(obj) + else: + attrib[tag] = obj + + return cls(**attrib) + + + def to_tree(self, tagname=None, idx=None, namespace=None): + + if tagname is None: + tagname = self.tagname + + # keywords have to be masked + if tagname.startswith("_"): + tagname = tagname[1:] + + tagname = namespaced(self, tagname, namespace) + namespace = getattr(self, "namespace", namespace) + + attrs = dict(self) + for key, ns in self.__namespaced__: + if key in attrs: + attrs[ns] = attrs[key] + del attrs[key] + + el = Element(tagname, attrs) + if "attr_text" in self.__attrs__: + el.text = safe_string(getattr(self, "attr_text")) + + for child_tag in self.__elements__: + desc = getattr(self.__class__, child_tag, None) + obj = getattr(self, child_tag) + if hasattr(desc, "namespace") and hasattr(obj, 'namespace'): + obj.namespace = desc.namespace + + if isinstance(obj, seq_types): + if isinstance(desc, NestedSequence): + # wrap sequence in container + if not obj: + continue + nodes = [desc.to_tree(child_tag, obj, namespace)] + elif isinstance(desc, Sequence): + # sequence + desc.idx_base = self.idx_base + nodes = (desc.to_tree(child_tag, obj, namespace)) + else: # property + nodes = (v.to_tree(child_tag, namespace) for v in obj) + for node in nodes: + el.append(node) + else: + if child_tag in self.__nested__: + node = desc.to_tree(child_tag, obj, namespace) + elif obj is None: + continue + else: + node = obj.to_tree(child_tag) + if node is not None: + el.append(node) + return el + + + def __iter__(self): + for attr in self.__attrs__: + value = getattr(self, attr) + if attr.startswith("_"): + attr = attr[1:] + elif attr != "attr_text" and "_" in attr: + desc = getattr(self.__class__, attr) + if getattr(desc, "hyphenated", False): + attr = attr.replace("_", "-") + if attr != "attr_text" and value is not None: + yield attr, safe_string(value) + + + def __eq__(self, other): + if not self.__class__ == other.__class__: + return False + elif not dict(self) == dict(other): + return False + for el in self.__elements__: + if getattr(self, el) != getattr(other, el): + return False + return True + + + def __ne__(self, other): + return not self == other + + + def __repr__(self): + s = u"<{0}.{1} object>\nParameters:".format( + self.__module__, + self.__class__.__name__ + ) + args = [] + for k in self.__attrs__ + self.__elements__: + v = getattr(self, k) + if isinstance(v, Descriptor): + v = None + args.append(u"{0}={1}".format(k, repr(v))) + args = u", ".join(args) + + return u"\n".join([s, args]) + + + def __hash__(self): + fields = [] + for attr in self.__attrs__ + self.__elements__: + val = getattr(self, attr) + if isinstance(val, list): + val = tuple(val) + fields.append(val) + + return hash(tuple(fields)) + + + def __add__(self, other): + if type(self) != type(other): + raise TypeError("Cannot combine instances of different types") + vals = {} + for attr in self.__attrs__: + vals[attr] = getattr(self, attr) or getattr(other, attr) + for el in self.__elements__: + a = getattr(self, el) + b = getattr(other, el) + if a and b: + vals[el] = a + b + else: + vals[el] = a or b + return self.__class__(**vals) + + + def __copy__(self): + # serialise to xml and back to avoid shallow copies + xml = self.to_tree(tagname="dummy") + cp = self.__class__.from_tree(xml) + # copy any non-persisted attributed + for k in self.__dict__: + if k not in self.__attrs__ + self.__elements__: + v = copy(getattr(self, k)) + setattr(cp, k, v) + return cp diff --git a/venv/Lib/site-packages/openpyxl/descriptors/slots.py b/venv/Lib/site-packages/openpyxl/descriptors/slots.py new file mode 100644 index 0000000..cadc1ef --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/descriptors/slots.py @@ -0,0 +1,18 @@ +# Metaclass for mixing slots and descriptors +# From "Programming in Python 3" by Mark Summerfield Ch.8 p. 383 + +class AutoSlotProperties(type): + + def __new__(mcl, classname, bases, dictionary): + slots = list(dictionary.get("__slots__", [])) + for getter_name in [key for key in dictionary if key.startswith("get_")]: + name = getter_name + slots.append("__" + name) + getter = dictionary.pop(getter_name) + setter = dictionary.get(setter_name, None) + if (setter is not None + and isinstance(setter, collections.Callable)): + del dictionary[setter_name] + dictionary[name] = property(getter. setter) + dictionary["__slots__"] = tuple(slots) + return super().__new__(mcl, classname, bases, dictionary) diff --git a/venv/Lib/site-packages/openpyxl/drawing/__init__.py b/venv/Lib/site-packages/openpyxl/drawing/__init__.py new file mode 100644 index 0000000..02f0587 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/drawing/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) 2010-2024 openpyxl + + +from .drawing import Drawing diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/__init__.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b8c798e3955c8f536909cffcf47c75c14709abc GIT binary patch literal 240 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 NSU>)efP!no{{bsB2N?hW literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/connector.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/connector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f948d15774475f8ea271b9eac8a62a6617075448 GIT binary patch literal 4937 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 z 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 O_n}??+Y$=asQ&>wf#A~s literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/geometry.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/geometry.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4275974bd95c5146f7b5ce47a3df0caae16aec43 GIT binary patch literal 19889 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/graphic.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/graphic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1beed8b660a353b35f8052cfd123a5957616cb1e GIT binary patch literal 5600 zcmb_gPi))P87C!De<{h5tUs1zS^kqaY7;k2+9nIKCa#^hSzN`9-EJieXo^TXTuD)V zR8l)|2OV-SuoeimLk;X=^f1gz4n6L;n~s#k-8j6!GR)_U#7L~lXspO;4$;A4 z-=R7+PUL9Ysq&gjbZKtUt$9R`<`unEAmFAC7+C6^k|f?`k$i6Po|t3z5?3~LcF zqD93h)p^umEhffj+pEU4gqYBhVp1CsN2t!HrnFIUl(zk9S{oC`SjNFDGLmqgkpeRJ z&}rE%W~ep@+E9;noN9+a8}89&sWt-IXpeS+YKK7^>(Ne9Z5*_T9_CP6#Wqn+ML zL@BC@QM{$fInLx)w<@w^a&PIn zYPwdcL@95W{G6&34HzA`vRReOhN7336r=hbV1v*0U0Gk3OI1{vA*(&Fm#amkER&oQ zo~0@kGrmZQk|LL@R~1!VCVE9CRYf+;2wv^ip;^mHsd|UVS4mNm;Tf^KUVdLO?iAGp zQv4Wf!Y3GJ)K)JN{Z3`&cCjLx!`*gw9yEUbc9B$X%4)F+F93?*uNH2ul499d*NJv! zp=4oaNv_>F`~n)EGcqHx5+gbsjO>)yM~;X1>TrnM3mX0fjq3%C`vr~X1&tRpKG_em zIUhROvk6|N_b0g|{yr-Pwz!nxx>t`I5(aJe4>VviNWv#OKU5yUi5n1r*y3=(S%RdQRxIO@kf>y*B@$ z$3w5Ph|IPNdL5r;w%yQkbsoCK?6Y~WpD*i+q+XK2-c}&ib)pars6Ob&52^5nkrcg|yI0nMN z_s+JDf8UzFu=buI6Ju>vm!#R1tMhB~MWa-dWMI*6U`}IADprdHMXTtfDwDOla{2Ds zl5%U!P^$8&O0o1|aYHuNfZ65B)~5Q3WHI%X4GWjq%9iOV6qK@3Efnsh2cR|Ex%v_s zcMe32c@|;fqdVNEzUJuh9j@U?Hj`QC2AY|Z*d1-g)6n&IwAlO1e+aiSId|SVazUK8 z431PNn7%?m)1^BqwuM6BBk(Be3UR|dKeA|unHj&azOIzyIa2Kl26RQq2^g`@kQ_d1 z21T+Xvd}O#K-_1Z3PZaK4Pl~o7 zyQ_`BWbJCt)j*^^aqe#mjli|q)n_gynQo3vG*g*ocDe~|Xe86EP>3J1Y{2OU`}G1` z>H4+Aicau1PUa;?kH4YkabhVz_L$*P{%$Yc%Vd>|!u5FGK!NROn0@of!rcU8;c0koKx6EnqEF7k53#lSa)8V*8WxoINIo(6jy z3gmhODaR40!5DG@1;qeu?9hm6QDNZo`e~FINF$p(t9TdUPRS#LcYgk4IQQpwzx<#v zd}-%OGnS&k&7ZFOr=MgmJf16zkkbX>m z+u^bEe~Ti{J469)Vtv$sd>*VP=qm#thYE|vIkdqBTEVf11qFII0l0c7yr22#O639r zA;je}y+}a=Qm9NYClfk34I44+q8S94HxS9ocmc();csB*K_o|Oi_M`_?b=h{(C<#v z<`0DMUf{3O4dGJl3IwrurkNPUa4~A3cp2_0!QVb`HarfI8G})j-Ms+p%F zoPb%Ny+k)|Vd-GH+o+MB!Q=8Jbi>YJhkXp6)bo8^&+jnhsL$I8fWA1HgIjYBE97I_ zz=!q)dn~`PI<)MuLEFT^BOm}Y7b7I<{>+oqu|J;LxlZeiuRTd?eQ35h8sRM;L;%SZ z6cn(_*g_iyVzr1DP<#Y`BMSntN_4P_B=$aRM9$Q%gE5)OmXqgatoiYl!T8kRNR3!n+~X@U|jhPw5)+p?4|;X-x}n;yRh%}=GrPfH2g zPDmWy&O|oVoV2dD6AG>CZHs7K@9x~wp`nLHQu=Nr4j0KgC@9$Yk|dAf28f)?A}Owd zHK_l(ffGS~fupBViS;h7&D~F7sId$JxEo{y$RJZs#$S6p{zhF$H?ya)N*QbVLpv9r zL?<3cr*;;a!$}BA-ljjYbLmNZ>JR$PVl$BemC#8;sc9&mLsq!rY4w~74~$xr>NJJW zHyQNKG?393$K|4LPu|4V2^2@F9!x?6MGgK2)&S@iX~;&2bp7Sajl^7?8$R$4?f$mm zpRFw%1fzSW8o|@G#RDO-D>Z~ENLJz4-f$y)y!MN4qwmsGH8srXZpIEcj`Bg8lae}tW=f>22t9u(%!z4tbnxy3k=g) zQA+tz=QTjnt)_9M|CfDio73byxDTqL<8bOuL=YMS=Q%=A*nM|CK-dKR3yy6ES09s_ z0;UB!gp0<3X&#GdPGDLtbd+b5Vpw%sv!kDyQP{;>pFz623o?vj=qe1|rJqQ8u7&X$ z+Wf=RyNOp(?7`naCxso_P^>mfOuIEY9H!`P?xx-q|0|ZffdmNiQ4KB2;Ns zddGz|C+rcDY?O#nsp`a-g`K(mor+*^GKU9^vyu??IO>3O*;0c>&dQr5StUMr6u~VC zd_bU|v50`00BX2(_z*#Y*bku?LZut1hM%SguC3{-*q^ej0-7R*keD9Q{?tUUh%ud; z60w3~61rB6O(V!o{aUd@nHU4fZ+bWF5~v9P9WO1LAuh!%jYT^meDeVa8jo5q50%WQ&1Q>%72@?WrvW zPOVIYJ-fTqV&K$zDaejKfH81tO$zMH1JJ{%l^J7?J-FCn;MBUzhS|h}^!E&$DB}MC DP(sq9 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/image.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/image.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9cb29a7b6ceaaee79aeb586a994813e5e7d94dc4 GIT binary patch literal 2604 zcmai0&2JM&6rcUF9ow;!=7W$zv*jbjscS;1O4L+T`5+{OrU=Rb%hGn^oy2QwuRFU= zuyLdaMU}0lb*ffMkdS~wOA$!?1wFLaUJ?ZfcNL^a<-#o_R7ITnX6>~RO4}Ft&D%F` z-psuD&2RF1W1|~^$Uj|-JrEH3lYZF3SB;(XU@RjADNF(-nJ~kk2KvP&*d!O`8Km$F zDC}U-X`~1XNO9a_D6+h9X0<9+ee*j%Zf?h$0)Zq*{3~iOk^COysOO8PQb(zn7Mymtie> zgl0}>uOyBtM4nYs(?_i}hSFKHu{stSh$LQ^)&oENeNgl0v8QFjw|BMk%(`!U)iwUa z)3y}7(RcIY^^*@hJsZCEQnHv_8Cv&=1#Z*hn?JJyqfnG8TdJ5qJAL3;Mi_+|1%+9K z33Cb?<^dgo!iOCcL1Cxj0PVsJigN+ot7Zthv#vmcRiRwFRYoYhD2sZUU|G>)7#mM% zv2yK4VSh=isB&d@S9|9|SC7q^?7*?8y$YJMhAS@&TSj>%kEH5c2-T65XABx?iH(;z z)^OUsd<}VXT%OwvJrS4{a=(H~sfNV{1Y>-5u6i49uG_X{R|0a?XJ<(>WN5Qv>a88k zpe+0yM8+F-AKXVb+()|KS{}HW-L;#^PMBOeH68Gn9KlnBUI>%Z4Pv3fL_6Pk_#JPgK(DMCrdY)s1JvSetI z)n^J8@N`;h5rk0mnJ!6EQ>r0JIiGdpA^UqD^y(Q<^JufBy}&QJHaZU6I)0y9?+6we zH=6dZMAw@R6om4DckcAu?pbqnL5zE8_=oW=o@)@xon1GB*MpBbgKM3^_0CXXcyauh z19|sudYen*#qn=G-4fvI#d85Qy|s-PYeZrA+wm<9?3X${onN{JdeN`FO@kcw8_R&+ zowfQbbk+GKkK(VQ5E4XkJC&xe#g_?vZNQXgu*p->A#Z{sz!M5a3)AGF6+svG z8juBvI&(n$z^)!a(w!<0k)rT$|7YG?17r?>3&mqv;s z6qYN@;zYT*b-De!_Tu1^=8o_876xheXmNDu{4Jp{`q0~5_WDYvi>H?c7SC+@n@h9B z*{`z&zU*?BTt(NSyXKPI9O%^&O(sV zvJtCPnUhonj=;Lt)|*!$0G>wV+?BFX`xBU7e;X8Be1A(RSIj-~i)()IR_mRP+Z{iD z@Sy*0|GNLgs_TTc$q67aAd!@u#FAvXB`K*XnFO`HlJsRpPE>oGlB8%+Nh0q;YSIJB zbjYb_Oe3U=dX7+!D^1`5B}SIev%8C|8LV|$&yuAm6I+kw0{Vj&H{G83p|bbT{Hbzd z^Zdv*-zao$i%ml7RyT6^p0SM3x5L?1B^|x|69K2ms#*nb9Q@l*$xmMmLMgif(c{#j zCt2mnk1KmSNj?N0t)YGb6fhRU{N+H*9$-GE?J<9N+wElhf42sizHJ2R#nyi0Y5|gC d+RFacYol~P+e@9^f`Vfoy5a2Req_42e*g)e7$N`w literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/line.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/line.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0eba273f1a43c3d0be0d44984334cd45f0be52b GIT binary patch literal 4442 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/picture.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/picture.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42faec60d51928e81f40f53c062ce8cc97538551 GIT binary patch literal 4381 zcmbVPOKcn06`dhx$l*^E|N2>?Y}pp$n67_~lR6(+Kf6$A)soY8Ab=fno}@{J9QMuF z77ZHU!V4`Lz&jf#P-qp{a28n>=qAem*$6NTkOK#BPJzS2+5or5Vzdlfo%2C#q^ucmWj^eC)`Mnh@m%6Z94^P(!MPhV zzq?jgEEZNk3$GBWDY|AVw{(&dY;m<#C8{l4F$~@Ityom6Y}n$At|=y1N9MOIQZY57 zvZR?70EtDaR5!JfqAydUN~om~^GDv9D1JrPstcOl(*<9o3P$Bq&AhGXb5ywtqvMA- zc5r1=sgf0|rjwGhb4LmtWiJlnKH>-`^C~BMR9^NHK^8q6@u{A#yw7k}D6+o~k@}E8 z9}?_CLVZZM4~g_41AR!e4;k!3Vt~X+0`?(1^K|x+R7E)z;12&&CDs3cm(w+0E?^HV zYbEP8B}+!>bG$C8s+F*9u0DlhRdn6BTdWur^3-ET$X1n{PTY5~wBR||p`aJ3L<%yAK^aZmX|E@b;E#w>8i7AwXgt=dw>SRue63xOMkWe-6A zrc&7;GbZjG?SEt3A!vAmnA$yJhbzXss#(j1ReVq=&+UN+1Q50h+j-VJvF@YkBViLts6vsf=KC)#knU;xn zk?k%2xi$O2+D(&Cb8Xd7)%?oB?AokimK2qM?|cSZGS^haQi@u+YEX;NwL7G8XKhKl zwPtD-IbBsspDP>0TmuKKRBK!M8P)N;Gr$w%O}<*QrD9R5XjZX!FLRJh`EJKMurBjc z5Do727?(M+E&MsuN{v7jYz<|higdN{cejP6G}=m!F`G{3*fgTUt%*F=W38hXu%2j5 zp4%4wA&u|B$XqU5=qb4jE~}!HNwH`Li^Z~`-qx`lE*Ad;0i@I8x0DTRQskZ;z@`a% zCKMU=f8GW~uG;DA>+4#H%uwq<+@r^_6BYq9D-)nhu}DwiTxk^3C{Cb&hs6;oXqbNo z@ql|dFw|IV4UROf{maJ<#2>FVBS#wx?eO5^xn_8>G2f0R9$U@mRO4z7mKxq!ZKmF7 z6xxwk_luwG5}BO~&BSzLshu9#QJd*gjqB~7%cZF0t65pMC z@0+=1ipfjOfD-5s)1Bj=g>Lu8&;@Llc8C_*jrT{yuuhB=fE>BJ2Wk zUht1xgyz78qDRtGDBeZE=+4%G-|C{F|SE=uq{C(TOJ) znxnti6^7c;3UWf_%DoMjBl z4$lhpz2AdCJ~Rd__kmM+)uVdhQSN+kpJ&gZ+h6xIf)Xmo2KqEK%SUJ_PiA6zq0z={c{%HijZ# z;v@%oHvGS*;j&A?56*)Cc1c_~w*BFYWbVmtzy8BFm1gqh_Ix*fhZ4J?(HEJs&ok$@ zuO48Z2gnyXlzeyyhpqVSl=~%qfdUWSL}nu8GL6L_!m-`##b)>tM#JRpu@9TkPa0QW zVuXWu#RAm680az#M<~I+ThR5e?0pHMpJDwG=>US+qeKF5<(*5GF*B4%s0YD3P$H2Y z1hc-VD!Sibh9{92jO=ssxwz_=6TR7-8dL+o;bcvMBqrRswFQbC@K&`_Cy-r&T|i<{ z1@f|(CeZf~k#2R8YdV9fXky-6D7k4AfNrGQ0p;f-UEO;qkG(9xb9r1Bz{*X=T(%1= z@pHYPE`pVtP`XwkO9YXl@dfafEG}hG8T03JOdD z+0N-Kv~qsOE#?tjK!IoESmN<8BNOKaSHaQ~mQ%e4@4Cu;ud}F)w3|!!~%>dElAaiH-iBWpn@s#N&FqPkxNOC=B>Ft02%P z6X=ui$7(Zt3|umn+DSHJCmO$Q4T-9+CI#aUkA=IsQ8Tio5uVoBEzR z{XLi6_nqd?KU~}ApxXZy!XC8zwdkgTRa{Sps9bnwz8NKgnuC8Hn}l)`7ane5Hvv(b)h6GqKIRk?ko8f zKOg&bsU$0MDWC*OK_yrUDWOtW36~;Dq!d-6e2%2YN^vCtV_6I69i>jCvy@bloDb?< zrIeBq1)ne{XrX(87AF43erJ89n@b}gjW$WsTp9yuyh+-_r3sLBG)a58v=gMsCTSm+ zc7Zh2B<)}C&ZfV`rL!W7%wC=T>|$;%pIZPfwm@i6)r*#TT_@QflNZ;^L}Suf)6`k; zqG6L|LYaSo*etMM)1tA=rlOD+$uOKaj4W_UQ!r55Qw0NnxObJQSti(A}xcB z{vbZ_KgK1XDKba{B&bPGg8!54}=YIL&(F(X&XM^8oCmM4L@)VEdeJ1*YHO{SQj3Nxvazj*YA8{ zYJ^E^H)x3kEp9N41<0B`Z`oOyNfyy>&~f-aeFw>5Bu9W)xT_4d|B{(gOV=zyt))d% z(^$YQ9)1o75(B={7NLFU=RPFIk|pV`Wg8x=gGkP`^=L zU(=^Fs@?(Dn<{%2nJllfP(EKYigrGKcetI=Cf&y)xVsFHitr*P^bX&bzKYhm`=ATg zdPks()p~~ROJ7G{!WfXKY}>&OR+A9i7&*;`RCEj?E_O!XRFca%Ir=ewRQMUS~c-uWo{?lwLSWyzsy$S z7c1vq1cd(KTF*cYXx~sh9F~Wj)o`KqF*pXE(;9!P+Ewi9uUNhjJEM%AqM2D!xCs$3IB@ApNiuM(=XxJ9(FwAM~=Bj01 zPz_B71Wvji;n0j(DjTO+*b)5z$&ZnoLh>OJ1Vj20Bp)I97|9tV(@4%D;h2S{;F#qS zC-^WL@1~n=>VXM<%K8)tfXR^1GYIezaZ#i%16;h89^k@}iThGDG*~-$68i%jV*q#> zlZK968oXr=<)l~-$NrjCbKbwAh%_E=`mQ3P9m8?@&hCY-7JjYV*y|iiWYvo zE_T(xwQ>e0@9KhM)(=sJT0x8hgO&&wBA@5b#67nOolfFhB#2ekUx6Sx4OHf8odcDN z&tsjNv(?yW<=jr9YZJie5P(rfYSXTEj8!h|>^@ERZ!K2SM=QCVcye>G8b4S$-!!j( z_+fXoe{x&u*-7hUN7#xTE z*}?Vq$OqXo+SX;cn{n6STksr?&f<Ad6Xeh;Lk$%Z1~ypWY5;pQ>~husa)D) z^Ml;x!=q?bS(3*ctKvu6TXhMZyp>harjl2BVv>_cxW NEp$UqB6$Q!+@vN{YDOg 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/text.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/text.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba7d39fabda183609f5f14a7f8693310b57a1123 GIT binary patch literal 21241 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

`|x*| z-gx2u(1Awy5X>A?s&OdU)fhXE%ONBAR-4T^QV$GyEvtOTKK{ zkGAciLjwN9O%MmPoD=jPTY)Qrei{fAdpm@Y07Rg|OQHG1annVC12UU=M%!xsaMeNC z`q8oKK{yv$Kc>cC#gMdAr*ta!hpJ#5p+E@s6xIb{x)FR!yM*x8(FQveaZtIQSBh$s zsl+9kIBOf~n6xZ@XieuiaZ*NQN3f;VYh}1zDjv*N%5ZeXPvr<3qvp%=r`4(|9p$hy zSme*CseQ~#!v-u{xaO`75Epm-D8f{_F9c+D>qk zV46T!Eq{}t-y!&YfPAV+3<&7Ndf%O?Q*$32}rJIKJ5y*x;~WvJ|XzD*W>E?NCNmYW@M>OgC0(O85rJ28 z|BGF&p*#DV65q|g;|aM2ZWf!Uf1o+&clF&y3|`Gt#5F=XUd=6O*XZr_ri54XuE2l4CB>2JfhR_YMyeTRz?_=r*F@& k@^mxR>l(UUY)W`FkA_?a?uax8nuC{E`S2$a-$E7ozdCyLF8}}l literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/drawing/__pycache__/xdr.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/drawing/__pycache__/xdr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ece5e527768c8d55b34119e745789f9d3925aa7 GIT binary patch literal 1358 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/pivot/__pycache__/fields.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/pivot/__pycache__/fields.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6dda34c9944ebeb2a79fdca802d29581dc66b0a7 GIT binary patch literal 8178 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 e1YieYH=madug~ogcr>{_ZZ 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

24fI6TjC|W9l@`O-AxiAs%&4;-N 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/styles/__pycache__/stylesheet.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/styles/__pycache__/stylesheet.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..374c8cc2cc2ad222a30329fad30c386c50c73ec2 GIT binary patch literal 11606 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 qeT~^SEet}CedD0$k!RNPCfdIgenw&W literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/styles/__pycache__/table.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/styles/__pycache__/table.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1ab6809ef31cf7253c27f732440647ea3e226ee GIT binary patch literal 3259 zcmb7G&2JM&6rZ(s?e*HRNpj2&t#OH|x)Y9y*ENy!p+{n>RbZ z_hx?W>e2`l>&F{wZ$bML8;zpWm7Q-u*(5fxC5IFxLy}MrIiX_M2p45TE-Hpnj2Mw( z)QA>ULoLRPSWz=H7#Fr>Ctge#35kTrMPe%th#jHQ^Kf9>=n`lYP_+$B3N!|&)`q64 zaXs-GC+ZSUWGO3HPQkO59jdEbS*n()&6NemwR|pLa9xLov()F&%O#(#QpTehw?q+% zWPMgBt#UO>?^I|hPhU%cO=Z?~T$T@93#43c?0f~vCZWWTY+{6L$q0uCl~>_A{2=`l zevTHP7z&^fTmDIDBGG+_8YB2;t9JB(WW=fwJ;u{ZxR0z~b?Cf9i?rnPw7(b9hq-od z&2^|4%wucRvMIan-s7t8`j&%Qe5JrVA2w1cmbm6vO+6_(U1>U*jz<3~g`9PHR@3-1%A_6_e5R=^&(*D%o= znCJw1#QaVyRkl{?LV-H=qP0vNkGFuEmQ$e~5Ik~MXiLu|u33)b-ZM+U-%P&2NTgc` zei%tRlOQ(9hO|LU(1NlNf>xcEglvSNh2ur3l4nvz4|CavsNu3#Sf^aE@2_08bs3t} zSz*UuAe%-p1H!{)N1^;<&YsHM@F??gORjBCW*262vzC_!CSGIiEt>beoNf7*StyoW z=2MotOG|fii-qN!SMcd4Wh;LhHt*%!GA)&>_nj#ZN$*VwwojI;Ts6%?soyV0mJ6qrVIzfysTQQPBnrcf`DUqtQ)~Rq! zoSH~mOAJZ)EX2F${W8#i+9r~VO#!M)tQ)FKJ_52)n&iC#$p0blh744$Um!qi1zOFZ zs1kM*%;^f3@hrJgF5Go}t_VN5l6Na5U-+U&*rza%&7qh_v4G+t3iQ=OSCR0eqrq9@ z;jj0$_THo-(!u)(1W+;Apdxbck+$7gjU9U^|E`XRQ`Qw=W`=zZ^Ym_Z5-N5I#c330 zP~gQJxQDK^`6yT^9F1d#AR)Spe5S$W;hCmjtFYfj*mF1m#mDgTZh%0-4kBUG-=08f zc0ZZhN{rR!+qDK=Uk;4Em^%N<($>KB7joaLUcI&$Fc?T2{Er{mjmMSgU`1T#!#plS z&wd_vuo5p)xdVv+5~XSfPh-GS&5juH23Kv(R^d`j&@LOE56#F(R-<~HCtIhtSnzxv zZ?V@4=*zwU&w#Dxu?h<|@U%@=tcv5eCO4sLNG`$tOuq42f|>jBGG=1LMG={}m6wss zZFxDMZI*yFE=(;W18X%IE?SE}dn%;vf8&;6Dff1!>C5hQ2YpG{Y(U8odK@^tG^77MFu z{?X$>kfr`R$XXv%1e6Gp^RO-3|$PV z#6-4q1zh9`U)vwmUxsSI-1D?OBG8XFPK60*E(ZNs``0 zh;;gWC?;;BKT}8hVo0B~b0o^h?u^hf$y2of(iO9_QW>sKmbi1!CAW AbpQYW literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/styles/alignment.py b/venv/Lib/site-packages/openpyxl/styles/alignment.py new file mode 100644 index 0000000..a727f67 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/alignment.py @@ -0,0 +1,62 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.compat import safe_string + +from openpyxl.descriptors import Bool, MinMax, Min, Alias, NoneSet +from openpyxl.descriptors.serialisable import Serialisable + + +horizontal_alignments = ( + "general", "left", "center", "right", "fill", "justify", "centerContinuous", + "distributed", ) +vertical_aligments = ( + "top", "center", "bottom", "justify", "distributed", +) + +class Alignment(Serialisable): + """Alignment options for use in styles.""" + + tagname = "alignment" + + horizontal = NoneSet(values=horizontal_alignments) + vertical = NoneSet(values=vertical_aligments) + textRotation = NoneSet(values=range(181)) + textRotation.values.add(255) + text_rotation = Alias('textRotation') + wrapText = Bool(allow_none=True) + wrap_text = Alias('wrapText') + shrinkToFit = Bool(allow_none=True) + shrink_to_fit = Alias('shrinkToFit') + indent = MinMax(min=0, max=255) + relativeIndent = MinMax(min=-255, max=255) + justifyLastLine = Bool(allow_none=True) + readingOrder = Min(min=0) + + def __init__(self, horizontal=None, vertical=None, + textRotation=0, wrapText=None, shrinkToFit=None, indent=0, relativeIndent=0, + justifyLastLine=None, readingOrder=0, text_rotation=None, + wrap_text=None, shrink_to_fit=None, mergeCell=None): + self.horizontal = horizontal + self.vertical = vertical + self.indent = indent + self.relativeIndent = relativeIndent + self.justifyLastLine = justifyLastLine + self.readingOrder = readingOrder + if text_rotation is not None: + textRotation = text_rotation + if textRotation is not None: + self.textRotation = int(textRotation) + if wrap_text is not None: + wrapText = wrap_text + self.wrapText = wrapText + if shrink_to_fit is not None: + shrinkToFit = shrink_to_fit + self.shrinkToFit = shrinkToFit + # mergeCell is vestigial + + + def __iter__(self): + for attr in self.__attrs__: + value = getattr(self, attr) + if value is not None and value != 0: + yield attr, safe_string(value) diff --git a/venv/Lib/site-packages/openpyxl/styles/borders.py b/venv/Lib/site-packages/openpyxl/styles/borders.py new file mode 100644 index 0000000..f9fce81 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/borders.py @@ -0,0 +1,103 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.compat import safe_string +from openpyxl.descriptors import ( + NoneSet, + Typed, + Bool, + Alias, + Sequence, + Integer, +) +from openpyxl.descriptors.serialisable import Serialisable + +from .colors import ColorDescriptor + + +BORDER_NONE = None +BORDER_DASHDOT = 'dashDot' +BORDER_DASHDOTDOT = 'dashDotDot' +BORDER_DASHED = 'dashed' +BORDER_DOTTED = 'dotted' +BORDER_DOUBLE = 'double' +BORDER_HAIR = 'hair' +BORDER_MEDIUM = 'medium' +BORDER_MEDIUMDASHDOT = 'mediumDashDot' +BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot' +BORDER_MEDIUMDASHED = 'mediumDashed' +BORDER_SLANTDASHDOT = 'slantDashDot' +BORDER_THICK = 'thick' +BORDER_THIN = 'thin' + + +class Side(Serialisable): + + """Border options for use in styles. + Caution: if you do not specify a border_style, other attributes will + have no effect !""" + + + color = ColorDescriptor(allow_none=True) + style = NoneSet(values=('dashDot','dashDotDot', 'dashed','dotted', + 'double','hair', 'medium', 'mediumDashDot', 'mediumDashDotDot', + 'mediumDashed', 'slantDashDot', 'thick', 'thin') + ) + border_style = Alias('style') + + def __init__(self, style=None, color=None, border_style=None): + if border_style is not None: + style = border_style + self.style = style + self.color = color + + +class Border(Serialisable): + """Border positioning for use in styles.""" + + tagname = "border" + + __elements__ = ('start', 'end', 'left', 'right', 'top', 'bottom', + 'diagonal', 'vertical', 'horizontal') + + # child elements + start = Typed(expected_type=Side, allow_none=True) + end = Typed(expected_type=Side, allow_none=True) + left = Typed(expected_type=Side, allow_none=True) + right = Typed(expected_type=Side, allow_none=True) + top = Typed(expected_type=Side, allow_none=True) + bottom = Typed(expected_type=Side, allow_none=True) + diagonal = Typed(expected_type=Side, allow_none=True) + vertical = Typed(expected_type=Side, allow_none=True) + horizontal = Typed(expected_type=Side, allow_none=True) + # attributes + outline = Bool() + diagonalUp = Bool() + diagonalDown = Bool() + + def __init__(self, left=None, right=None, top=None, + bottom=None, diagonal=None, diagonal_direction=None, + vertical=None, horizontal=None, diagonalUp=False, diagonalDown=False, + outline=True, start=None, end=None): + self.left = left + self.right = right + self.top = top + self.bottom = bottom + self.diagonal = diagonal + self.vertical = vertical + self.horizontal = horizontal + self.diagonal_direction = diagonal_direction + self.diagonalUp = diagonalUp + self.diagonalDown = diagonalDown + self.outline = outline + self.start = start + self.end = end + + def __iter__(self): + for attr in self.__attrs__: + value = getattr(self, attr) + if value and attr != "outline": + yield attr, safe_string(value) + elif attr == "outline" and not value: + yield attr, safe_string(value) + +DEFAULT_BORDER = Border(left=Side(), right=Side(), top=Side(), bottom=Side(), diagonal=Side()) diff --git a/venv/Lib/site-packages/openpyxl/styles/builtins.py b/venv/Lib/site-packages/openpyxl/styles/builtins.py new file mode 100644 index 0000000..7095eb3 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/builtins.py @@ -0,0 +1,1397 @@ +# Copyright (c) 2010-2024 openpyxl + +# Builtins styles as defined in Part 4 Annex G.2 + +from .named_styles import NamedStyle +from openpyxl.xml.functions import fromstring + + +normal = """ + + + + + + + + + + + + + + + + + + + + +""" + +comma = """ + + + _-* #,##0.00\\ _$_-;\\-* #,##0.00\\ _$_-;_-* "-"??\\ _$_-;_-@_- + + + + + + + + + + + + + + + + + + +""" + +comma_0 = """ + + + _-* #,##0\\ _$_-;\\-* #,##0\\ _$_-;_-* "-"\\ _$_-;_-@_- + + + + + + + + + + + + + + + + + + +""" + +currency = """ + + + _-* #,##0.00\\ "$"_-;\\-* #,##0.00\\ "$"_-;_-* "-"??\\ "$"_-;_-@_- + + + + + + + + + + + + + + + + + + +""" + +currency_0 = """ + + + _-* #,##0\\ "$"_-;\\-* #,##0\\ "$"_-;_-* "-"\\ "$"_-;_-@_- + + + + + + + + + + + + + + + + + + +""" + +percent = """ + + + 0% + + + + + + + + + + + + + + + + + + +""" + +hyperlink = """ + + + + + + + + + + + + + + + + + + + + """ + +followed_hyperlink = """ + + + + + + + + + + + + + + + + + + + + """ + +title = """ + + + + + + + + + + + + + + + + + + + + + +""" + +headline_1 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +headline_2 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +headline_3 = """ + + + + + + + + + + + + + + + + + + + + + + + + +""" + +headline_4 = """ + + + + + + + + + + + + + + + + + + + + + +""" + +good = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +bad = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +neutral = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +input = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +output = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +calculation = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +linked_cell = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +check_cell = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +warning = """ + + + + + + + + + + + + + + + + + + + + +""" + +note = """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +explanatory = """ + + + + + + + + + + + + + + + + + + + + + +""" + +total = """ + + + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_1 = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_1_20 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_1_40 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_1_60 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_2 = """ + + + + + + + + + + + + + + + + + + + + + """ + +accent_2_20 = """ + + + + + + + + + + + + + + + + + + + + + + + """ + +accent_2_40 = """ + + + + + + + + + + + + + + + + + + + + + + + """ + +accent_2_60 = """ + + + + + + + + + + + + + + + + + + + + + + + """ + +accent_3 = """ + + + + + + + + + + + + + + + + + + + + + + """ + +accent_3_20 = """ + + + + + + + + + + + + + + + + + + + + + + + """ + +accent_3_40 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" +accent_3_60 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" +accent_4 = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_4_20 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_4_40 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_4_60 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_5 = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_5_20 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_5_40 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_5_60 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_6 = """ + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_6_20 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_6_40 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +accent_6_60 = """ + + + + + + + + + + + + + + + + + + + + + + + +""" + +pandas_highlight = """ + +""" + +styles = dict( + [ + ('Normal', NamedStyle.from_tree(fromstring(normal))), + ('Comma', NamedStyle.from_tree(fromstring(comma))), + ('Currency', NamedStyle.from_tree(fromstring(currency))), + ('Percent', NamedStyle.from_tree(fromstring(percent))), + ('Comma [0]', NamedStyle.from_tree(fromstring(comma_0))), + ('Currency [0]', NamedStyle.from_tree(fromstring(currency_0))), + ('Hyperlink', NamedStyle.from_tree(fromstring(hyperlink))), + ('Followed Hyperlink', NamedStyle.from_tree(fromstring(followed_hyperlink))), + ('Note', NamedStyle.from_tree(fromstring(note))), + ('Warning Text', NamedStyle.from_tree(fromstring(warning))), + ('Title', NamedStyle.from_tree(fromstring(title))), + ('Headline 1', NamedStyle.from_tree(fromstring(headline_1))), + ('Headline 2', NamedStyle.from_tree(fromstring(headline_2))), + ('Headline 3', NamedStyle.from_tree(fromstring(headline_3))), + ('Headline 4', NamedStyle.from_tree(fromstring(headline_4))), + ('Input', NamedStyle.from_tree(fromstring(input))), + ('Output', NamedStyle.from_tree(fromstring(output))), + ('Calculation',NamedStyle.from_tree(fromstring(calculation))), + ('Check Cell', NamedStyle.from_tree(fromstring(check_cell))), + ('Linked Cell', NamedStyle.from_tree(fromstring(linked_cell))), + ('Total', NamedStyle.from_tree(fromstring(total))), + ('Good', NamedStyle.from_tree(fromstring(good))), + ('Bad', NamedStyle.from_tree(fromstring(bad))), + ('Neutral', NamedStyle.from_tree(fromstring(neutral))), + ('Accent1', NamedStyle.from_tree(fromstring(accent_1))), + ('20 % - Accent1', NamedStyle.from_tree(fromstring(accent_1_20))), + ('40 % - Accent1', NamedStyle.from_tree(fromstring(accent_1_40))), + ('60 % - Accent1', NamedStyle.from_tree(fromstring(accent_1_60))), + ('Accent2', NamedStyle.from_tree(fromstring(accent_2))), + ('20 % - Accent2', NamedStyle.from_tree(fromstring(accent_2_20))), + ('40 % - Accent2', NamedStyle.from_tree(fromstring(accent_2_40))), + ('60 % - Accent2', NamedStyle.from_tree(fromstring(accent_2_60))), + ('Accent3', NamedStyle.from_tree(fromstring(accent_3))), + ('20 % - Accent3', NamedStyle.from_tree(fromstring(accent_3_20))), + ('40 % - Accent3', NamedStyle.from_tree(fromstring(accent_3_40))), + ('60 % - Accent3', NamedStyle.from_tree(fromstring(accent_3_60))), + ('Accent4', NamedStyle.from_tree(fromstring(accent_4))), + ('20 % - Accent4', NamedStyle.from_tree(fromstring(accent_4_20))), + ('40 % - Accent4', NamedStyle.from_tree(fromstring(accent_4_40))), + ('60 % - Accent4', NamedStyle.from_tree(fromstring(accent_4_60))), + ('Accent5', NamedStyle.from_tree(fromstring(accent_5))), + ('20 % - Accent5', NamedStyle.from_tree(fromstring(accent_5_20))), + ('40 % - Accent5', NamedStyle.from_tree(fromstring(accent_5_40))), + ('60 % - Accent5', NamedStyle.from_tree(fromstring(accent_5_60))), + ('Accent6', NamedStyle.from_tree(fromstring(accent_6))), + ('20 % - Accent6', NamedStyle.from_tree(fromstring(accent_6_20))), + ('40 % - Accent6', NamedStyle.from_tree(fromstring(accent_6_40))), + ('60 % - Accent6', NamedStyle.from_tree(fromstring(accent_6_60))), + ('Explanatory Text', NamedStyle.from_tree(fromstring(explanatory))), + ('Pandas', NamedStyle.from_tree(fromstring(pandas_highlight))) + ] +) diff --git a/venv/Lib/site-packages/openpyxl/styles/cell_style.py b/venv/Lib/site-packages/openpyxl/styles/cell_style.py new file mode 100644 index 0000000..51091aa --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/cell_style.py @@ -0,0 +1,206 @@ +# Copyright (c) 2010-2024 openpyxl + +from array import array + +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.descriptors import ( + Typed, + Float, + Bool, + Integer, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.utils.indexed_list import IndexedList + + +from .alignment import Alignment +from .protection import Protection + + +class ArrayDescriptor: + + def __init__(self, key): + self.key = key + + def __get__(self, instance, cls): + return instance[self.key] + + def __set__(self, instance, value): + instance[self.key] = value + + +class StyleArray(array): + """ + Simplified named tuple with an array + """ + + __slots__ = () + tagname = 'xf' + + fontId = ArrayDescriptor(0) + fillId = ArrayDescriptor(1) + borderId = ArrayDescriptor(2) + numFmtId = ArrayDescriptor(3) + protectionId = ArrayDescriptor(4) + alignmentId = ArrayDescriptor(5) + pivotButton = ArrayDescriptor(6) + quotePrefix = ArrayDescriptor(7) + xfId = ArrayDescriptor(8) + + + def __new__(cls, args=[0]*9): + return array.__new__(cls, 'i', args) + + + def __hash__(self): + return hash(tuple(self)) + + + def __copy__(self): + return StyleArray((self)) + + + def __deepcopy__(self, memo): + return StyleArray((self)) + + +class CellStyle(Serialisable): + + tagname = "xf" + + numFmtId = Integer() + fontId = Integer() + fillId = Integer() + borderId = Integer() + xfId = Integer(allow_none=True) + quotePrefix = Bool(allow_none=True) + pivotButton = Bool(allow_none=True) + applyNumberFormat = Bool(allow_none=True) + applyFont = Bool(allow_none=True) + applyFill = Bool(allow_none=True) + applyBorder = Bool(allow_none=True) + applyAlignment = Bool(allow_none=True) + applyProtection = Bool(allow_none=True) + alignment = Typed(expected_type=Alignment, allow_none=True) + protection = Typed(expected_type=Protection, allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = ('alignment', 'protection') + __attrs__ = ("numFmtId", "fontId", "fillId", "borderId", + "applyAlignment", "applyProtection", "pivotButton", "quotePrefix", "xfId") + + def __init__(self, + numFmtId=0, + fontId=0, + fillId=0, + borderId=0, + xfId=None, + quotePrefix=None, + pivotButton=None, + applyNumberFormat=None, + applyFont=None, + applyFill=None, + applyBorder=None, + applyAlignment=None, + applyProtection=None, + alignment=None, + protection=None, + extLst=None, + ): + self.numFmtId = numFmtId + self.fontId = fontId + self.fillId = fillId + self.borderId = borderId + self.xfId = xfId + self.quotePrefix = quotePrefix + self.pivotButton = pivotButton + self.applyNumberFormat = applyNumberFormat + self.applyFont = applyFont + self.applyFill = applyFill + self.applyBorder = applyBorder + self.alignment = alignment + self.protection = protection + + + def to_array(self): + """ + Convert to StyleArray + """ + style = StyleArray() + for k in ("fontId", "fillId", "borderId", "numFmtId", "pivotButton", + "quotePrefix", "xfId"): + v = getattr(self, k, 0) + if v is not None: + setattr(style, k, v) + return style + + + @classmethod + def from_array(cls, style): + """ + Convert from StyleArray + """ + return cls(numFmtId=style.numFmtId, fontId=style.fontId, + fillId=style.fillId, borderId=style.borderId, xfId=style.xfId, + quotePrefix=style.quotePrefix, pivotButton=style.pivotButton,) + + + @property + def applyProtection(self): + return self.protection is not None or None + + + @property + def applyAlignment(self): + return self.alignment is not None or None + + +class CellStyleList(Serialisable): + + tagname = "cellXfs" + + __attrs__ = ("count",) + + count = Integer(allow_none=True) + xf = Sequence(expected_type=CellStyle) + alignment = Sequence(expected_type=Alignment) + protection = Sequence(expected_type=Protection) + + __elements__ = ('xf',) + + def __init__(self, + count=None, + xf=(), + ): + self.xf = xf + + + @property + def count(self): + return len(self.xf) + + + def __getitem__(self, idx): + try: + return self.xf[idx] + except IndexError: + print((f"{idx} is out of range")) + return self.xf[idx] + + + def _to_array(self): + """ + Extract protection and alignments, convert to style array + """ + self.prots = IndexedList([Protection()]) + self.alignments = IndexedList([Alignment()]) + styles = [] # allow duplicates + for xf in self.xf: + style = xf.to_array() + if xf.alignment is not None: + style.alignmentId = self.alignments.add(xf.alignment) + if xf.protection is not None: + style.protectionId = self.prots.add(xf.protection) + styles.append(style) + return IndexedList(styles) diff --git a/venv/Lib/site-packages/openpyxl/styles/colors.py b/venv/Lib/site-packages/openpyxl/styles/colors.py new file mode 100644 index 0000000..6fa7476 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/colors.py @@ -0,0 +1,172 @@ +# Copyright (c) 2010-2024 openpyxl + +import re +from openpyxl.compat import safe_string +from openpyxl.descriptors import ( + String, + Bool, + MinMax, + Integer, + Typed, +) +from openpyxl.descriptors.sequence import NestedSequence +from openpyxl.descriptors.serialisable import Serialisable + +# Default Color Index as per 18.8.27 of ECMA Part 4 +COLOR_INDEX = ( + '00000000', '00FFFFFF', '00FF0000', '0000FF00', '000000FF', #0-4 + '00FFFF00', '00FF00FF', '0000FFFF', '00000000', '00FFFFFF', #5-9 + '00FF0000', '0000FF00', '000000FF', '00FFFF00', '00FF00FF', #10-14 + '0000FFFF', '00800000', '00008000', '00000080', '00808000', #15-19 + '00800080', '00008080', '00C0C0C0', '00808080', '009999FF', #20-24 + '00993366', '00FFFFCC', '00CCFFFF', '00660066', '00FF8080', #25-29 + '000066CC', '00CCCCFF', '00000080', '00FF00FF', '00FFFF00', #30-34 + '0000FFFF', '00800080', '00800000', '00008080', '000000FF', #35-39 + '0000CCFF', '00CCFFFF', '00CCFFCC', '00FFFF99', '0099CCFF', #40-44 + '00FF99CC', '00CC99FF', '00FFCC99', '003366FF', '0033CCCC', #45-49 + '0099CC00', '00FFCC00', '00FF9900', '00FF6600', '00666699', #50-54 + '00969696', '00003366', '00339966', '00003300', '00333300', #55-59 + '00993300', '00993366', '00333399', '00333333', #60-63 +) +# indices 64 and 65 are reserved for the system foreground and background colours respectively + +# Will remove these definitions in a future release +BLACK = COLOR_INDEX[0] +WHITE = COLOR_INDEX[1] +#RED = COLOR_INDEX[2] +#DARKRED = COLOR_INDEX[8] +BLUE = COLOR_INDEX[4] +#DARKBLUE = COLOR_INDEX[12] +#GREEN = COLOR_INDEX[3] +#DARKGREEN = COLOR_INDEX[9] +#YELLOW = COLOR_INDEX[5] +#DARKYELLOW = COLOR_INDEX[19] + + +aRGB_REGEX = re.compile("^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6})$") + + +class RGB(Typed): + """ + Descriptor for aRGB values + If not supplied alpha is 00 + """ + + expected_type = str + + def __set__(self, instance, value): + if not self.allow_none: + m = aRGB_REGEX.match(value) + if m is None: + raise ValueError("Colors must be aRGB hex values") + if len(value) == 6: + value = "00" + value + super().__set__(instance, value) + + +class Color(Serialisable): + """Named colors for use in styles.""" + + tagname = "color" + + rgb = RGB() + indexed = Integer() + auto = Bool() + theme = Integer() + tint = MinMax(min=-1, max=1, expected_type=float) + type = String() + + + def __init__(self, rgb=BLACK, indexed=None, auto=None, theme=None, tint=0.0, index=None, type='rgb'): + if index is not None: + indexed = index + if indexed is not None: + self.type = 'indexed' + self.indexed = indexed + elif theme is not None: + self.type = 'theme' + self.theme = theme + elif auto is not None: + self.type = 'auto' + self.auto = auto + else: + self.rgb = rgb + self.type = 'rgb' + self.tint = tint + + @property + def value(self): + return getattr(self, self.type) + + @value.setter + def value(self, value): + setattr(self, self.type, value) + + def __iter__(self): + attrs = [(self.type, self.value)] + if self.tint != 0: + attrs.append(('tint', self.tint)) + for k, v in attrs: + yield k, safe_string(v) + + @property + def index(self): + # legacy + return self.value + + + def __add__(self, other): + """ + Adding colours is undefined behaviour best do nothing + """ + if not isinstance(other, Color): + return super().__add__(other) + return self + + +class ColorDescriptor(Typed): + + expected_type = Color + + def __set__(self, instance, value): + if isinstance(value, str): + value = Color(rgb=value) + super().__set__(instance, value) + + +class RgbColor(Serialisable): + + tagname = "rgbColor" + + rgb = RGB() + + def __init__(self, + rgb=None, + ): + self.rgb = rgb + + +class ColorList(Serialisable): + + tagname = "colors" + + indexedColors = NestedSequence(expected_type=RgbColor) + mruColors = NestedSequence(expected_type=Color) + + __elements__ = ('indexedColors', 'mruColors') + + def __init__(self, + indexedColors=(), + mruColors=(), + ): + self.indexedColors = indexedColors + self.mruColors = mruColors + + + def __bool__(self): + return bool(self.indexedColors) or bool(self.mruColors) + + + @property + def index(self): + return [val.rgb for val in self.indexedColors] diff --git a/venv/Lib/site-packages/openpyxl/styles/differential.py b/venv/Lib/site-packages/openpyxl/styles/differential.py new file mode 100644 index 0000000..109577e --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/differential.py @@ -0,0 +1,95 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors import ( + Typed, + Sequence, + Alias, +) +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.styles import ( + Font, + Fill, + Border, + Alignment, + Protection, + ) +from .numbers import NumberFormat + + +class DifferentialStyle(Serialisable): + + tagname = "dxf" + + __elements__ = ("font", "numFmt", "fill", "alignment", "border", "protection") + + font = Typed(expected_type=Font, allow_none=True) + numFmt = Typed(expected_type=NumberFormat, allow_none=True) + fill = Typed(expected_type=Fill, allow_none=True) + alignment = Typed(expected_type=Alignment, allow_none=True) + border = Typed(expected_type=Border, allow_none=True) + protection = Typed(expected_type=Protection, allow_none=True) + + def __init__(self, + font=None, + numFmt=None, + fill=None, + alignment=None, + border=None, + protection=None, + extLst=None, + ): + self.font = font + self.numFmt = numFmt + self.fill = fill + self.alignment = alignment + self.border = border + self.protection = protection + self.extLst = extLst + + +class DifferentialStyleList(Serialisable): + """ + Dedupable container for differential styles. + """ + + tagname = "dxfs" + + dxf = Sequence(expected_type=DifferentialStyle) + styles = Alias("dxf") + __attrs__ = ("count",) + + + def __init__(self, dxf=(), count=None): + self.dxf = dxf + + + def append(self, dxf): + """ + Check to see whether style already exists and append it if does not. + """ + if not isinstance(dxf, DifferentialStyle): + raise TypeError('expected ' + str(DifferentialStyle)) + if dxf in self.styles: + return + self.styles.append(dxf) + + + def add(self, dxf): + """ + Add a differential style and return its index + """ + self.append(dxf) + return self.styles.index(dxf) + + + def __bool__(self): + return bool(self.styles) + + + def __getitem__(self, idx): + return self.styles[idx] + + + @property + def count(self): + return len(self.dxf) diff --git a/venv/Lib/site-packages/openpyxl/styles/fills.py b/venv/Lib/site-packages/openpyxl/styles/fills.py new file mode 100644 index 0000000..7071abd --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/fills.py @@ -0,0 +1,224 @@ + +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.descriptors import ( + Float, + Set, + Alias, + NoneSet, + Sequence, + Integer, + MinMax, +) +from openpyxl.descriptors.serialisable import Serialisable +from openpyxl.compat import safe_string + +from .colors import ColorDescriptor, Color + +from openpyxl.xml.functions import Element, localname +from openpyxl.xml.constants import SHEET_MAIN_NS + + +FILL_NONE = 'none' +FILL_SOLID = 'solid' +FILL_PATTERN_DARKDOWN = 'darkDown' +FILL_PATTERN_DARKGRAY = 'darkGray' +FILL_PATTERN_DARKGRID = 'darkGrid' +FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal' +FILL_PATTERN_DARKTRELLIS = 'darkTrellis' +FILL_PATTERN_DARKUP = 'darkUp' +FILL_PATTERN_DARKVERTICAL = 'darkVertical' +FILL_PATTERN_GRAY0625 = 'gray0625' +FILL_PATTERN_GRAY125 = 'gray125' +FILL_PATTERN_LIGHTDOWN = 'lightDown' +FILL_PATTERN_LIGHTGRAY = 'lightGray' +FILL_PATTERN_LIGHTGRID = 'lightGrid' +FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal' +FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis' +FILL_PATTERN_LIGHTUP = 'lightUp' +FILL_PATTERN_LIGHTVERTICAL = 'lightVertical' +FILL_PATTERN_MEDIUMGRAY = 'mediumGray' + +fills = (FILL_SOLID, FILL_PATTERN_DARKDOWN, FILL_PATTERN_DARKGRAY, + FILL_PATTERN_DARKGRID, FILL_PATTERN_DARKHORIZONTAL, FILL_PATTERN_DARKTRELLIS, + FILL_PATTERN_DARKUP, FILL_PATTERN_DARKVERTICAL, FILL_PATTERN_GRAY0625, + FILL_PATTERN_GRAY125, FILL_PATTERN_LIGHTDOWN, FILL_PATTERN_LIGHTGRAY, + FILL_PATTERN_LIGHTGRID, FILL_PATTERN_LIGHTHORIZONTAL, + FILL_PATTERN_LIGHTTRELLIS, FILL_PATTERN_LIGHTUP, FILL_PATTERN_LIGHTVERTICAL, + FILL_PATTERN_MEDIUMGRAY) + + +class Fill(Serialisable): + + """Base class""" + + tagname = "fill" + + @classmethod + def from_tree(cls, el): + children = [c for c in el] + if not children: + return + child = children[0] + if "patternFill" in child.tag: + return PatternFill._from_tree(child) + return super(Fill, GradientFill).from_tree(child) + + +class PatternFill(Fill): + """Area fill patterns for use in styles. + Caution: if you do not specify a fill_type, other attributes will have + no effect !""" + + tagname = "patternFill" + + __elements__ = ('fgColor', 'bgColor') + + patternType = NoneSet(values=fills) + fill_type = Alias("patternType") + fgColor = ColorDescriptor() + start_color = Alias("fgColor") + bgColor = ColorDescriptor() + end_color = Alias("bgColor") + + def __init__(self, patternType=None, fgColor=Color(), bgColor=Color(), + fill_type=None, start_color=None, end_color=None): + if fill_type is not None: + patternType = fill_type + self.patternType = patternType + if start_color is not None: + fgColor = start_color + self.fgColor = fgColor + if end_color is not None: + bgColor = end_color + self.bgColor = bgColor + + @classmethod + def _from_tree(cls, el): + attrib = dict(el.attrib) + for child in el: + desc = localname(child) + attrib[desc] = Color.from_tree(child) + return cls(**attrib) + + + def to_tree(self, tagname=None, idx=None): + parent = Element("fill") + el = Element(self.tagname) + if self.patternType is not None: + el.set('patternType', self.patternType) + for c in self.__elements__: + value = getattr(self, c) + if value != Color(): + el.append(value.to_tree(c)) + parent.append(el) + return parent + + +DEFAULT_EMPTY_FILL = PatternFill() +DEFAULT_GRAY_FILL = PatternFill(patternType='gray125') + + +class Stop(Serialisable): + + tagname = "stop" + + position = MinMax(min=0, max=1) + color = ColorDescriptor() + + def __init__(self, color, position): + self.position = position + self.color = color + + +def _assign_position(values): + """ + Automatically assign positions if a list of colours is provided. + + It is not permitted to mix colours and stops + """ + n_values = len(values) + n_stops = sum(isinstance(value, Stop) for value in values) + + if n_stops == 0: + interval = 1 + if n_values > 2: + interval = 1 / (n_values - 1) + values = [Stop(value, i * interval) + for i, value in enumerate(values)] + + elif n_stops < n_values: + raise ValueError('Cannot interpret mix of Stops and Colors in GradientFill') + + pos = set() + for stop in values: + if stop.position in pos: + raise ValueError("Duplicate position {0}".format(stop.position)) + pos.add(stop.position) + + return values + + +class StopList(Sequence): + + expected_type = Stop + + def __set__(self, obj, values): + values = _assign_position(values) + super().__set__(obj, values) + + +class GradientFill(Fill): + """Fill areas with gradient + + Two types of gradient fill are supported: + + - A type='linear' gradient interpolates colours between + a set of specified Stops, across the length of an area. + The gradient is left-to-right by default, but this + orientation can be modified with the degree + attribute. A list of Colors can be provided instead + and they will be positioned with equal distance between them. + + - A type='path' gradient applies a linear gradient from each + edge of the area. Attributes top, right, bottom, left specify + the extent of fill from the respective borders. Thus top="0.2" + will fill the top 20% of the cell. + + """ + + tagname = "gradientFill" + + type = Set(values=('linear', 'path')) + fill_type = Alias("type") + degree = Float() + left = Float() + right = Float() + top = Float() + bottom = Float() + stop = StopList() + + + def __init__(self, type="linear", degree=0, left=0, right=0, top=0, + bottom=0, stop=()): + self.degree = degree + self.left = left + self.right = right + self.top = top + self.bottom = bottom + self.stop = stop + self.type = type + + + def __iter__(self): + for attr in self.__attrs__: + value = getattr(self, attr) + if value: + yield attr, safe_string(value) + + + def to_tree(self, tagname=None, namespace=None, idx=None): + parent = Element("fill") + el = super().to_tree() + parent.append(el) + return parent diff --git a/venv/Lib/site-packages/openpyxl/styles/fonts.py b/venv/Lib/site-packages/openpyxl/styles/fonts.py new file mode 100644 index 0000000..06e343f --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/fonts.py @@ -0,0 +1,113 @@ +# Copyright (c) 2010-2024 openpyxl + + +from openpyxl.descriptors import ( + Alias, + Sequence, + Integer +) +from openpyxl.descriptors.serialisable import Serialisable + +from openpyxl.descriptors.nested import ( + NestedValue, + NestedBool, + NestedNoneSet, + NestedMinMax, + NestedString, + NestedInteger, + NestedFloat, +) +from .colors import ColorDescriptor, Color, BLACK + +from openpyxl.compat import safe_string +from openpyxl.xml.functions import Element, SubElement +from openpyxl.xml.constants import SHEET_MAIN_NS + + +def _no_value(tagname, value, namespace=None): + if value: + return Element(tagname, val=safe_string(value)) + + +class Font(Serialisable): + """Font options used in styles.""" + + UNDERLINE_DOUBLE = 'double' + UNDERLINE_DOUBLE_ACCOUNTING = 'doubleAccounting' + UNDERLINE_SINGLE = 'single' + UNDERLINE_SINGLE_ACCOUNTING = 'singleAccounting' + + name = NestedString(allow_none=True) + charset = NestedInteger(allow_none=True) + family = NestedMinMax(min=0, max=14, allow_none=True) + sz = NestedFloat(allow_none=True) + size = Alias("sz") + b = NestedBool(to_tree=_no_value) + bold = Alias("b") + i = NestedBool(to_tree=_no_value) + italic = Alias("i") + strike = NestedBool(allow_none=True) + strikethrough = Alias("strike") + outline = NestedBool(allow_none=True) + shadow = NestedBool(allow_none=True) + condense = NestedBool(allow_none=True) + extend = NestedBool(allow_none=True) + u = NestedNoneSet(values=('single', 'double', 'singleAccounting', + 'doubleAccounting')) + underline = Alias("u") + vertAlign = NestedNoneSet(values=('superscript', 'subscript', 'baseline')) + color = ColorDescriptor(allow_none=True) + scheme = NestedNoneSet(values=("major", "minor")) + + tagname = "font" + + __elements__ = ('name', 'charset', 'family', 'b', 'i', 'strike', 'outline', + 'shadow', 'condense', 'color', 'extend', 'sz', 'u', 'vertAlign', + 'scheme') + + + def __init__(self, name=None, sz=None, b=None, i=None, charset=None, + u=None, strike=None, color=None, scheme=None, family=None, size=None, + bold=None, italic=None, strikethrough=None, underline=None, + vertAlign=None, outline=None, shadow=None, condense=None, + extend=None): + self.name = name + self.family = family + if size is not None: + sz = size + self.sz = sz + if bold is not None: + b = bold + self.b = b + if italic is not None: + i = italic + self.i = i + if underline is not None: + u = underline + self.u = u + if strikethrough is not None: + strike = strikethrough + self.strike = strike + self.color = color + self.vertAlign = vertAlign + self.charset = charset + self.outline = outline + self.shadow = shadow + self.condense = condense + self.extend = extend + self.scheme = scheme + + + @classmethod + def from_tree(cls, node): + """ + Set default value for underline if child element is present + """ + underline = node.find("{%s}u" % SHEET_MAIN_NS) + if underline is not None and underline.get('val') is None: + underline.set("val", "single") + return super().from_tree(node) + + +DEFAULT_FONT = Font(name="Calibri", sz=11, family=2, b=False, i=False, + color=Color(theme=1), scheme="minor") diff --git a/venv/Lib/site-packages/openpyxl/styles/named_styles.py b/venv/Lib/site-packages/openpyxl/styles/named_styles.py new file mode 100644 index 0000000..221d333 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/named_styles.py @@ -0,0 +1,282 @@ +# Copyright (c) 2010-2024 openpyxl + +from openpyxl.compat import safe_string + +from openpyxl.descriptors import ( + Typed, + Integer, + Bool, + String, + Sequence, +) +from openpyxl.descriptors.excel import ExtensionList +from openpyxl.descriptors.serialisable import Serialisable + +from .fills import PatternFill, Fill +from .fonts import Font +from .borders import Border +from .alignment import Alignment +from .protection import Protection +from .numbers import ( + NumberFormatDescriptor, + BUILTIN_FORMATS_MAX_SIZE, + BUILTIN_FORMATS_REVERSE, +) +from .cell_style import ( + StyleArray, + CellStyle, +) + + +class NamedStyle(Serialisable): + + """ + Named and editable styles + """ + + font = Typed(expected_type=Font) + fill = Typed(expected_type=Fill) + border = Typed(expected_type=Border) + alignment = Typed(expected_type=Alignment) + number_format = NumberFormatDescriptor() + protection = Typed(expected_type=Protection) + builtinId = Integer(allow_none=True) + hidden = Bool(allow_none=True) + name = String() + _wb = None + _style = StyleArray() + + + def __init__(self, + name="Normal", + font=None, + fill=None, + border=None, + alignment=None, + number_format=None, + protection=None, + builtinId=None, + hidden=False, + ): + self.name = name + self.font = font or Font() + self.fill = fill or PatternFill() + self.border = border or Border() + self.alignment = alignment or Alignment() + self.number_format = number_format + self.protection = protection or Protection() + self.builtinId = builtinId + self.hidden = hidden + self._wb = None + self._style = StyleArray() + + + def __setattr__(self, attr, value): + super().__setattr__(attr, value) + if getattr(self, '_wb', None) and attr in ( + 'font', 'fill', 'border', 'alignment', 'number_format', 'protection', + ): + self._recalculate() + + + def __iter__(self): + for key in ('name', 'builtinId', 'hidden', 'xfId'): + value = getattr(self, key, None) + if value is not None: + yield key, safe_string(value) + + + def bind(self, wb): + """ + Bind a named style to a workbook + """ + self._wb = wb + self._recalculate() + + + def _recalculate(self): + self._style.fontId = self._wb._fonts.add(self.font) + self._style.borderId = self._wb._borders.add(self.border) + self._style.fillId = self._wb._fills.add(self.fill) + self._style.protectionId = self._wb._protections.add(self.protection) + self._style.alignmentId = self._wb._alignments.add(self.alignment) + fmt = self.number_format + if fmt in BUILTIN_FORMATS_REVERSE: + fmt = BUILTIN_FORMATS_REVERSE[fmt] + else: + fmt = self._wb._number_formats.add(self.number_format) + ( + BUILTIN_FORMATS_MAX_SIZE) + self._style.numFmtId = fmt + + + def as_tuple(self): + """Return a style array representing the current style""" + return self._style + + + def as_xf(self): + """ + Return equivalent XfStyle + """ + xf = CellStyle.from_array(self._style) + xf.xfId = None + xf.pivotButton = None + xf.quotePrefix = None + if self.alignment != Alignment(): + xf.alignment = self.alignment + if self.protection != Protection(): + xf.protection = self.protection + return xf + + + def as_name(self): + """ + Return relevant named style + + """ + named = _NamedCellStyle( + name=self.name, + builtinId=self.builtinId, + hidden=self.hidden, + xfId=self._style.xfId + ) + return named + + +class NamedStyleList(list): + """ + Named styles are editable and can be applied to multiple objects + + As only the index is stored in referencing objects the order mus + be preserved. + + Returns a list of NamedStyles + """ + + def __init__(self, iterable=()): + """ + Allow a list of named styles to be passed in and index them. + """ + + for idx, s in enumerate(iterable, len(self)): + s._style.xfId = idx + super().__init__(iterable) + + + @property + def names(self): + return [s.name for s in self] + + + def __getitem__(self, key): + if isinstance(key, int): + return super().__getitem__(key) + + + for idx, name in enumerate(self.names): + if name == key: + return self[idx] + + raise KeyError("No named style with the name{0} exists".format(key)) + + def append(self, style): + if not isinstance(style, NamedStyle): + raise TypeError("""Only NamedStyle instances can be added""") + elif style.name in self.names: # hotspot + raise ValueError("""Style {0} exists already""".format(style.name)) + style._style.xfId = (len(self)) + super().append(style) + + +class _NamedCellStyle(Serialisable): + + """ + Pointer-based representation of named styles in XML + xfId refers to the corresponding CellStyleXfs + + Not used in client code. + """ + + tagname = "cellStyle" + + name = String() + xfId = Integer() + builtinId = Integer(allow_none=True) + iLevel = Integer(allow_none=True) + hidden = Bool(allow_none=True) + customBuiltin = Bool(allow_none=True) + extLst = Typed(expected_type=ExtensionList, allow_none=True) + + __elements__ = () + + + def __init__(self, + name=None, + xfId=None, + builtinId=None, + iLevel=None, + hidden=None, + customBuiltin=None, + extLst=None, + ): + self.name = name + self.xfId = xfId + self.builtinId = builtinId + self.iLevel = iLevel + self.hidden = hidden + self.customBuiltin = customBuiltin + + +class _NamedCellStyleList(Serialisable): + """ + Container for named cell style objects + + Not used in client code + """ + + tagname = "cellStyles" + + count = Integer(allow_none=True) + cellStyle = Sequence(expected_type=_NamedCellStyle) + + __attrs__ = ("count",) + + def __init__(self, + count=None, + cellStyle=(), + ): + self.cellStyle = cellStyle + + + @property + def count(self): + return len(self.cellStyle) + + + def remove_duplicates(self): + """ + Some applications contain duplicate definitions either by name or + referenced style. + + As the references are 0-based indices, styles are sorted by + index. + + Returns a list of style references with duplicates removed + """ + + def sort_fn(v): + return v.xfId + + styles = [] + names = set() + ids = set() + + for ns in sorted(self.cellStyle, key=sort_fn): + if ns.xfId in ids or ns.name in names: # skip duplicates + continue + ids.add(ns.xfId) + names.add(ns.name) + + styles.append(ns) + + return styles diff --git a/venv/Lib/site-packages/openpyxl/styles/numbers.py b/venv/Lib/site-packages/openpyxl/styles/numbers.py new file mode 100644 index 0000000..b548cc7 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/styles/numbers.py @@ -0,0 +1,200 @@ +# Copyright (c) 2010-2024 openpyxl + +import re + +from openpyxl.descriptors import ( + String, + Sequence, + Integer, +) +from openpyxl.descriptors.serialisable import Serialisable + + +BUILTIN_FORMATS = { + 0: 'General', + 1: '0', + 2: '0.00', + 3: '#,##0', + 4: '#,##0.00', + 5: '"$"#,##0_);("$"#,##0)', + 6: '"$"#,##0_);[Red]("$"#,##0)', + 7: '"$"#,##0.00_);("$"#,##0.00)', + 8: '"$"#,##0.00_);[Red]("$"#,##0.00)', + 9: '0%', + 10: '0.00%', + 11: '0.00E+00', + 12: '# ?/?', + 13: '# ??/??', + 14: 'mm-dd-yy', + 15: 'd-mmm-yy', + 16: 'd-mmm', + 17: 'mmm-yy', + 18: 'h:mm AM/PM', + 19: 'h:mm:ss AM/PM', + 20: 'h:mm', + 21: 'h:mm:ss', + 22: 'm/d/yy h:mm', + + 37: '#,##0_);(#,##0)', + 38: '#,##0_);[Red](#,##0)', + 39: '#,##0.00_);(#,##0.00)', + 40: '#,##0.00_);[Red](#,##0.00)', + + 41: r'_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)', + 42: r'_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)', + 43: r'_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)', + + 44: r'_("$"* #,##0.00_)_("$"* \(#,##0.00\)_("$"* "-"??_)_(@_)', + 45: 'mm:ss', + 46: '[h]:mm:ss', + 47: 'mmss.0', + 48: '##0.0E+0', + 49: '@', } + +BUILTIN_FORMATS_MAX_SIZE = 164 +BUILTIN_FORMATS_REVERSE = dict( + [(value, key) for key, value in BUILTIN_FORMATS.items()]) + +FORMAT_GENERAL = BUILTIN_FORMATS[0] +FORMAT_TEXT = BUILTIN_FORMATS[49] +FORMAT_NUMBER = BUILTIN_FORMATS[1] +FORMAT_NUMBER_00 = BUILTIN_FORMATS[2] +FORMAT_NUMBER_COMMA_SEPARATED1 = BUILTIN_FORMATS[4] +FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-' +FORMAT_PERCENTAGE = BUILTIN_FORMATS[9] +FORMAT_PERCENTAGE_00 = BUILTIN_FORMATS[10] +FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd' +FORMAT_DATE_YYMMDD = 'yy-mm-dd' +FORMAT_DATE_DDMMYY = 'dd/mm/yy' +FORMAT_DATE_DMYSLASH = 'd/m/y' +FORMAT_DATE_DMYMINUS = 'd-m-y' +FORMAT_DATE_DMMINUS = 'd-m' +FORMAT_DATE_MYMINUS = 'm-y' +FORMAT_DATE_XLSX14 = BUILTIN_FORMATS[14] +FORMAT_DATE_XLSX15 = BUILTIN_FORMATS[15] +FORMAT_DATE_XLSX16 = BUILTIN_FORMATS[16] +FORMAT_DATE_XLSX17 = BUILTIN_FORMATS[17] +FORMAT_DATE_XLSX22 = BUILTIN_FORMATS[22] +FORMAT_DATE_DATETIME = 'yyyy-mm-dd h:mm:ss' +FORMAT_DATE_TIME1 = BUILTIN_FORMATS[18] +FORMAT_DATE_TIME2 = BUILTIN_FORMATS[19] +FORMAT_DATE_TIME3 = BUILTIN_FORMATS[20] +FORMAT_DATE_TIME4 = BUILTIN_FORMATS[21] +FORMAT_DATE_TIME5 = BUILTIN_FORMATS[45] +FORMAT_DATE_TIME6 = BUILTIN_FORMATS[21] +FORMAT_DATE_TIME7 = 'i:s.S' +FORMAT_DATE_TIME8 = 'h:mm:ss@' +FORMAT_DATE_TIMEDELTA = '[hh]:mm:ss' +FORMAT_DATE_YYMMDDSLASH = 'yy/mm/dd@' +FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-' +FORMAT_CURRENCY_USD = '$#,##0_-' +FORMAT_CURRENCY_EUR_SIMPLE = '[$EUR ]#,##0.00_-' + + +COLORS = r"\[(BLACK|BLUE|CYAN|GREEN|MAGENTA|RED|WHITE|YELLOW)\]" +LITERAL_GROUP = r'".*?"' # anything in quotes +LOCALE_GROUP = r'\[(?!hh?\]|mm?\]|ss?\])[^\]]*\]' # anything in square brackets, except hours or minutes or seconds +STRIP_RE = re.compile(f"{LITERAL_GROUP}|{LOCALE_GROUP}") +TIMEDELTA_RE = re.compile(r'\[hh?\](:mm(:ss(\.0*)?)?)?|\[mm?\](:ss(\.0*)?)?|\[ss?\](\.0*)?', re.I) + + +# Spec 18.8.31 numFmts +# +ve;-ve;zero;text + +def is_date_format(fmt): + if fmt is None: + return False + fmt = fmt.split(";")[0] # only look at the first format + fmt = STRIP_RE.sub("", fmt) # ignore some formats + return re.search(r"(?;XZH!`tG@zT!ncQo= xkZzC0hZLUD-DVTYm&))~!YezC6VtD_XAwVhjPY$b#Mv!+z^~^Bzp&de`vNSrykxg0v>-x>zKE?M3=Au~J*x&JO0rZ5Uaw5D zFZ2ZIu*fEQK>EV=5>BKcT9`D6jchCMCYrQm%w^mq7NS!q7F&|Ew?t%#O(q|so>a4v zA9V zqM`pY{uZ`AKsWIxH9wy}zEvKWEEPHrDV4Fbl){QiMyQU4RFs#P?wZ`&-p%JJjTGFP zQsYK&3%l}2ZoJvLXoNPc3km1-%?~zO8_YzEi_di8U^OkyETgiYCfW+!+7atoq& z8EM5UDT}sQSD03kiZ~ryQtO$O%B;5?Md-gQsHX$%Sbq7;f5=mxP5lIT&2yk0UO@-X zoE??EK6Mx_?w9X`XRe>S9j@ItdpBGggC9KxrUPuOKshk23z^8i5AeZFhxir{)X5j# z5N(x;^GW^XXCyxu$PUnj&2Z9brC+0 zC=Yg+%7i`zAB-ErZ9qFJ=qEv4e)e%}j;lWHa$W@m@Ek6$eqX+`{Njy`yUQ<+f`jVP zca8nV?dsa$!c$k@zy8KgjUOAozW&F;`oYr5XhAQ#29s&ajwCVb3rh0}rTv6w%AFS| z{XAo8>M2volL#*27B-nIUz}1W5=sHVaB&5P>f6Qqj!@dEIe5%zP!IReUtSo5M=M@% z{z0V_tlmeUifLS=V{tV~lme2$ufk{t@1({}R75#s^6;%<%!Ym*OxMylEbjXl*C@A0c>6^8Nwo8ep;j literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/cell.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/cell.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61e6da7c91f61f4071ca4630f0013197d941ff66 GIT binary patch literal 9864 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/datetime.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/datetime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5dfd6849c964ddacb571e8ff3691af96ef31eb05 GIT binary patch literal 6302 zcmb7IYj7LKk=|XrUj)F1Oj07Xe945xhbYmKP7y`(0h^L7krqYSM)AUfFiQ~>h^1$j zvWWmTlG0UyNh*SKt`mJp#YoDPP$gBJ^6QeS`=Ot?${!$5ip++o($(q5=^thK*VSG5 zx@WNf#L)KLkeHdB>F#-Tf88^`_jsHfr0_3i7JlvLxc|TpBUwt7-BzCC?r?+)afByA zj1TcpnqtC|DP-dHHgm`tPoSEhInsrAusVk?vt$Z zJn`S+Lw?ChYUc$~2lZM~4}Eo{0rGls0P==aA@D-t(8X{(d|eWQ??H+b=(3IDp5mC%8(4Eg?P)7y*WvfdA7i5O4r1hu8U{7rbCIJI=hFb&f-Alu(B$J>A6|*oxxO~7r&R}xVnH1$4d<) zyjuDU3||>$%xZK=XI_w37&FkGVa(C^3dq&DyIGSWMdUa!ns9(!-n3%fKjgnBZ0$fJ}6M9nEX9{s-;edLsL`0xkBWp->04ga zoT@x`etPos$zuc53xghlpVALmntNia$mTT|M&S$e)IVzg~b<)IaEqRQ{e2upUi@vNSRWWq=lV*SB5BS0fu=YJTvlm%(yfF+{l&_)n z_lYBsh)f9}5A-`lNCT()22S-2iqW{JE=ZyRU=y8>M#5@T)?4P~SWJEoIl$^gG<#78 z9z_gOiOEn_mKmIoJ}3Jg2e?qg(Y}Gc0WlmWP&?i?z~PGdv|yObsjhE}%!ewxa4@mkshB1(Z{8p-W;ntQbK! zqKcD~Z(n>vT#|_t=n)ke`xOaSCx&D2xe_OUsH!Z(`f$rGQH&Y_R?UolRkJW}s+qut zYG!n4npJmWnpH<~hS*PE8TE3S84rXu06WDfg`(nVW?VN#+oN@up+zK`&c|^&iQh@xdszl~= zPexIDHOq3Cs)}a1A+1t063qm&R;*CNjT1$Rh@iRAHpM`v4B>`5;Rz(=C=f4bYWSIRJC1WxrfOH$XxRU|33WRgy5+ z*^{ayReW&SYl5T-I&+Krc%XZwktjwNaIeu51c`znSvg)cgYv2jN{(AZGu@M5*5&wQ z-}RU1jWJRX-z512+^`nQ9*2Ig3+n8Ea7XaZ6KtOk)-%cQUjD};E7&tJXdx}8_#Ul;4 zHD^?b#vy_Q1g2=T3`jIL!o?f}hJb+zJp%2TzlsaZ({!jWEh0{v+W-* z+*$f)>5;8-+k0?*wCFvYw;$ftJ2nq=7Y=kkvIVxiVy?F6?abRdw{7ms<=bzqy>;t@ zEql!qS8euq_U0p3>$az1)6-h;v~GHi6g)?A^#1989=bbpZ@B3BRz}#davpECVeP`E z>rlaUC_TPqvu6fxeULr=_aCfxeKz!m=3`rSca~psWXxMG@5epsv{>6-aJA>n?aZ=X zjg(aerd|$z|C^asl1qbvCI$L;71P-7=91*@SAtbj(zKuQ(X-zm!}N8*GBG7U3Dt6# zy#E-)Y^e5qi&2A+*#rhzWv0Yr^s$i2oU(lV%&JDUsCX4-3BzP!tqzv&+YGZ#S&2Of zparIbCSxHcW$bW?ONc@vAytnd8p#q?OF zaobh5>1rvsTJFF6pz&YdC=5*eZm=*gSv)%R$n~afa_|0AAL7h- z(c6}{w;>9=yaxqbnRnOh8Pk@__wnh?x~@W9*T#uQb^Qfb|AWqg>tx=1Qg^jwCkV?$ zY{1`c1~R-3FG9ID5gx5z|2GXHU?0;gZa-8g^!^g8{&zT&)FHYtbcsb{5npZ|?u=W#EajW&9&l zo)6OY^B|SiF^0)}N~qvg5}tFPLu^xuuUx_x_tBlCDG6Q+G_tHYFo{w!o*+PvgiAX9 zSm-(Eq-QYez^oZFM52J1DTQW++mylxGz)t%RLsy@#tZriGGMj_KLzzD&26Jee>(KZ z&_;W)z8B1TJoDmqZR2`9bHU$zJsr#pf|=hQS{qt#$eDB3H&!y8r+H literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/escape.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/escape.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ff3c72c5936561cc7fdc14c7000de8d7694230e GIT binary patch literal 1535 zcmb7^%TF6e9LHy0U>UoZK!}3UWsh-|c4b~o5$*|lcY zmhmHUr5w^zi(1J!x@wgcaq0ij3y}}0_Ef1SZZz(xr~YRANI|Wljr-roXtC9hVULo&D%FvHQ_J10M}!qBUd+rf3Umf+;;kYoaMbl(xmFQl1Omx^@4? z3eM^jJFXL>p6-}BF|kDrJ)d(n@FSOCBdZhL@GL^{JU$&fUD*uRC4?T~AR>tO}b-Z}iQ(Dpt{6cl|1gO68A(7+S`4iWc$k!fIw| z2?Wh1vFBp$BZXB5U%Q625}v_Xt2E^jb4qohQTVCx#pR&~Y9f)0sfpR-!y^_3;ownt z+IJy9+Jw!%i8qowW|Frm`Zvj@*t2&0%?(U*4cvro+v~dVm`Ufkws@9le?mE^l`5%3 zdahK{2ung#@&}+8Te{~=$Vihwka`M|H`%=Nn+4NFJ zVm!a?%Ni}Lm&dvt^R{c~HciJ_?+7TMlMw3YFn}UwUJXya9G?7PwpsYG@?GWUN~J2RZ@>s~GE`(-7+D&mcN6)|l9tcz&}rGE-lEEz8Q)!w?FMf0h0+{rr4WX$@W2 zmoJbIOg~coKEdlS^8X1or79{Sa^meI*H9G!401WeYu%%{p*dhF4|%3Lj~9kJ7=dHI-~w-VgHoWOGT^6hnR0%!PQ zAJNP|7%n&+1IH*nU@H$I5TLM z*66phUl$scok}zL&66f+jZU|QXZ8a#ysW;cl}H%oMkT_K^uvp*nT6YnpZq6Gf!?8n z{bf$TL$5-BvqI?PsmAio^8VSm*4X9x4aU<&;3*J#R`{a!YvkQmk#jF2=bGn#Qd*Jt zGv&9TNPUH?h|2z;rkSpxY2+Q)jFZau-$i^vhvUHfmTMMlD^1SAB$h3D8p5F@2*Mu& Wq9C^eNC>_j2n!#y@rW?Om;MdKflbT+ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/exceptions.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e241a7b1caa60568038713273ce2a2f1c0319d3d GIT binary patch literal 1883 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/protection.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/protection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7a242f7b0fdfea471ba7965cb12d196b016bd26 GIT binary patch literal 1220 zcmYjR&1)M+6ra_u9Lcg0k=pJD{TK+TQ9xS9Ati)hTI`fSOA=z6l(I$4?u@h>uXdK1 zku0ea^`Qrw=AhC-bM&dD_|pHQP%I3sSwb&8`DSoVy|iyulG_J6@4cD#d*AG@#o{ai za(~?NS51We(#n)F6XARggdY$!sqwY(IqGK0R)RcZY6d(DAE43spKySsF)-A{dmquv z;l$TE`rC>?$51x>w--}?s5jwJ<{F)8plroJ(?p7Ljf>Dzz&a3azfdg(2+fyz1Z6Qnwe zfz|{gieZ9dBIOPj6#GQ_xGs1TE*n9cMOZ2kL=9Z$0>^?Y<|(Zb4CdR?XH2D@cocT4 zc+(Fg-U-4GM_i>ADUL;+=*IuUxtwoTXH#GbX)@(=iUI5r$tdO#RzBnvHn<3s-_()Y z0fiU0o1)f96tECKVUg-#UdNAO7Coxh0}ntEO~H@vfAj?E^0rBXrI?Kvs-eva>X-STKrQ*A`?S{M|t4&EG zZDhMP6M?tmgI}8n&xa1$E6dAw?Bx}E<(3UaRYKMvUbmtf4UMc^)L03k3WqW(on}}i zGVY}DPWALo^=h47fg||mD>y#+4OG3556d%2o<*%D6EMfbgb5~Q$fCrAsU@b*I!U$_ z$4r3T)i@+Uq*zDQrqfPx7m^v!PGWgJ5lOa9!WK*BVA$Z4*4#izIRnx3#$f!nw|3Xr zl1xZvlT%vV_;}4(Bhn+3Jr?{K?1ywHQKS|$V=kb-4s21|`804H32muNMj{1+iHZdXZ^0+`;n+oI^Qg4A`{3omyGQTc{N?8F3%B?4d*U+&GFZX#V}<($dIU+I?_h%?)QpmJU$3{9F$2d^0#Myz@ul+Nf~txN!Y|9Joh?@{v_O yhh$&|hS0MBrnCGRiA7*y9*!h;ugPgEWUJy0Q1uk0{#%`yhGD$QT{Ui`w*LaqTUGu5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/openpyxl/utils/__pycache__/units.cpython-312.pyc b/venv/Lib/site-packages/openpyxl/utils/__pycache__/units.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcaffdf20b806207b8247466012ccf0f5baffa79 GIT binary patch literal 3110 zcmbtWTTdHD6y9AgV7y?!HjrQfQ!cHXE0B>34& zrdFFsp^8)^RSJFMscMuz(ErdEBflUk50P3`a{GetTc3K)co*!Ls8uu4d^0<@{pOo< z&djf^tu_JD-Jceh{80N1Kg=W85r3QfLJ)ZuUjNUA|*TQ3^$>>?03X>5L z2OCL-(gL|W1n^wY_xsjhj~Q5rN{BCw_FIC-l5vfaSR%4SJ|Q2Dk>g}+gwTiKk_#3n z%>ld+iEeQS0)I33m^VXEF>$@^+V*Mc;x zheNUDRFdf`3$Cb%mEe5rZcvNq>Zw#X@*o^lwO}%(CQ_>p<7d)(EUukNCt|vGI<;C< zkW)xchJXxfg?rNIvGog^()wgx?qPOl ztoil+DfB@P*q2y+4yN{a4nRZlMg70@J^AaVe90s7AJtK5HmF3FnG+TqhpgeIkVxAP zCpOiBV`y6$%F9FbR8Rq~!VFYu4Z){K3!UKn!`xuP+cHmI+!{XcG?P&GFnbHl3WV=S3Y(0VS0$Q4SAz~IY}4KA<1 z9y>Q(8@&akFE97Kt4@wl5?Kb3&YmBERFUb@qlUv}V(5|_W}#B97H4Js(Z3QRFsaro z;o!KNzBHnA#Z?DjTnUexp-U2yYJ@1iJr=EFN42EckF)SQqvn__6W<0{^EW zEqn_C)_H`eij&~^Yy226KxLGP^Ms~iC*gjGRbnQF!55O@=Fp|#BBp=0ANWlw2{(tv z&Oq;HkPUNvZG=zDw&Kpq?s`fXk~t+j$7&f40@Z!Ag*Va~k_PG(3o_lyEP1Tu^dUes z!_=a@9M+eLazu^A8NXd>cfq-%_Zv=k7Up~oS?dQt!?Hiqzh7Nn-R#_Q{^;If+ebZx zw&MlmL|#5of3*918iCn|@5#KQO~z))521UMP&LX_6&$nTm*GS-u4<(_e?rKW_>LGd ztMiTa$~+#(_#Ac~hJ_$&Xc|0}Jxk{nHy1a)D6|b0-g1+m;QUYsRH`>{aI@CBEZ$Qk zl=N_yZRcE2UxOc;fUy*^R_(c+8^^Z9f-;bo2kJ#dKAh7@sMK;Y#iQbb8KBSrEG25` zfh%_nuU$DaK<*_OSO5u=NHU&eL{AcUdk}32-YZ0lWmHnaLt}VB`8@CnimM4I8u;j% zrvjf6;_VEth$YAx#wpOY$@X;o+e~iin@2lsuH4O>|LJPpdIVk&*?GPnk65|`BRyRV z9~ec)jCXcwaeg7>zkWM3=e>GmZlP$uJax+(n!Y|Cx_xzKVXo*h$3WBKHJ{PyG+XDr zvkReXQ~oPgeFw`eT)$zq+0B7--l-X{pFgfD4-eFx-^u*4V+22Wc*mH^V^<}jpg%Ko z2X0CH-1xp3#s$8s%1v+mcsWVaarGjbg${f-YEJ-mEutuvt%BIHYZJPT<^{)2ha+p> z=^p-B-0t?|1=p@s=[A-Za-z]{1,3})? +[$]?(?P\d+)? +(:[$]?(?P[A-Za-z]{1,3})? +[$]?(?P\d+)?)? +""" +ABSOLUTE_RE = re.compile('^' + RANGE_EXPR +'$', re.VERBOSE) +SHEET_TITLE = r""" +(('(?P([^']|'')*)')|(?P[^'^ ^!]*))!""" +SHEETRANGE_RE = re.compile("""{0}(?P{1})(?=,?)""".format( + SHEET_TITLE, RANGE_EXPR), re.VERBOSE) + + +def get_column_interval(start, end): + """ + Given the start and end columns, return all the columns in the series. + + The start and end columns can be either column letters or 1-based + indexes. + """ + if isinstance(start, str): + start = column_index_from_string(start) + if isinstance(end, str): + end = column_index_from_string(end) + return [get_column_letter(x) for x in range(start, end + 1)] + + +def coordinate_from_string(coord_string): + """Convert a coordinate string like 'B12' to a tuple ('B', 12)""" + match = COORD_RE.match(coord_string) + if not match: + msg = f"Invalid cell coordinates ({coord_string})" + raise CellCoordinatesException(msg) + column, row = match.groups() + row = int(row) + if not row: + msg = f"There is no row 0 ({coord_string})" + raise CellCoordinatesException(msg) + return column, row + + +def absolute_coordinate(coord_string): + """Convert a coordinate to an absolute coordinate string (B12 -> $B$12)""" + m = ABSOLUTE_RE.match(coord_string) + if not m: + raise ValueError(f"{coord_string} is not a valid coordinate range") + + d = m.groupdict('') + for k, v in d.items(): + if v: + d[k] = f"${v}" + + if d['max_col'] or d['max_row']: + fmt = "{min_col}{min_row}:{max_col}{max_row}" + else: + fmt = "{min_col}{min_row}" + return fmt.format(**d) + + +__decimal_to_alpha = [""] + list(ascii_uppercase) + +@lru_cache(maxsize=None) +def get_column_letter(col_idx): + """ + Convert decimal column position to its ASCII (base 26) form. + + Because column indices are 1-based, strides are actually pow(26, n) + 26 + Hence, a correction is applied between pow(26, n) and pow(26, 2) + 26 to + prevent and additional column letter being prepended + + "A" == 1 == pow(26, 0) + "Z" == 26 == pow(26, 0) + 26 // decimal equivalent 10 + "AA" == 27 == pow(26, 1) + 1 + "ZZ" == 702 == pow(26, 2) + 26 // decimal equivalent 100 + """ + + if not 1 <= col_idx <= 18278: + raise ValueError("Invalid column index {0}".format(col_idx)) + + result = [] + + if col_idx < 26: + return __decimal_to_alpha[col_idx] + + while col_idx: + col_idx, remainder = divmod(col_idx, 26) + result.insert(0, __decimal_to_alpha[remainder]) + if not remainder: + col_idx -= 1 + result.insert(0, "Z") + + return "".join(result) + + +__alpha_to_decimal = {letter:pos for pos, letter in enumerate(ascii_uppercase, 1)} +__powers = (1, 26, 676) + +@lru_cache(maxsize=None) +def column_index_from_string(col): + """ + Convert ASCII column name (base 26) to decimal with 1-based index + + Characters represent descending multiples of powers of 26 + + "AFZ" == 26 * pow(26, 0) + 6 * pow(26, 1) + 1 * pow(26, 2) + """ + error_msg = f"'{col}' is not a valid column name. Column names are from A to ZZZ" + if len(col) > 3: + raise ValueError(error_msg) + idx = 0 + col = reversed(col.upper()) + for letter, power in zip(col, __powers): + try: + pos = __alpha_to_decimal[letter] + except KeyError: + raise ValueError(error_msg) + idx += pos * power + if not 0 < idx < 18279: + raise ValueError(error_msg) + return idx + + +def range_boundaries(range_string): + """ + Convert a range string into a tuple of boundaries: + (min_col, min_row, max_col, max_row) + Cell coordinates will be converted into a range with the cell at both end + """ + msg = "{0} is not a valid coordinate or range".format(range_string) + m = ABSOLUTE_RE.match(range_string) + if not m: + raise ValueError(msg) + + min_col, min_row, sep, max_col, max_row = m.groups() + + if sep: + cols = min_col, max_col + rows = min_row, max_row + + if not ( + all(cols + rows) or + all(cols) and not any(rows) or + all(rows) and not any(cols) + ): + raise ValueError(msg) + + if min_col is not None: + min_col = column_index_from_string(min_col) + + if min_row is not None: + min_row = int(min_row) + + if max_col is not None: + max_col = column_index_from_string(max_col) + else: + max_col = min_col + + if max_row is not None: + max_row = int(max_row) + else: + max_row = min_row + + return min_col, min_row, max_col, max_row + + +def rows_from_range(range_string): + """ + Get individual addresses for every cell in a range. + Yields one row at a time. + """ + min_col, min_row, max_col, max_row = range_boundaries(range_string) + rows = range(min_row, max_row + 1) + cols = [get_column_letter(col) for col in range(min_col, max_col + 1)] + for row in rows: + yield tuple('{0}{1}'.format(col, row) for col in cols) + + +def cols_from_range(range_string): + """ + Get individual addresses for every cell in a range. + Yields one row at a time. + """ + min_col, min_row, max_col, max_row = range_boundaries(range_string) + rows = range(min_row, max_row+1) + cols = (get_column_letter(col) for col in range(min_col, max_col+1)) + for col in cols: + yield tuple('{0}{1}'.format(col, row) for row in rows) + + +def coordinate_to_tuple(coordinate): + """ + Convert an Excel style coordinate to (row, column) tuple + """ + for idx, c in enumerate(coordinate): + if c in digits: + break + col = coordinate[:idx] + row = coordinate[idx:] + return int(row), column_index_from_string(col) + + +def range_to_tuple(range_string): + """ + Convert a worksheet range to the sheetname and maximum and minimum + coordinate indices + """ + m = SHEETRANGE_RE.match(range_string) + if m is None: + raise ValueError("Value must be of the form sheetname!A1:E4") + sheetname = m.group("quoted") or m.group("notquoted") + cells = m.group("cells") + boundaries = range_boundaries(cells) + return sheetname, boundaries + + +def quote_sheetname(sheetname): + """ + Add quotes around sheetnames if they contain spaces. + """ + if "'" in sheetname: + sheetname = sheetname.replace("'", "''") + + sheetname = u"'{0}'".format(sheetname) + return sheetname diff --git a/venv/Lib/site-packages/openpyxl/utils/dataframe.py b/venv/Lib/site-packages/openpyxl/utils/dataframe.py new file mode 100644 index 0000000..f56a488 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/utils/dataframe.py @@ -0,0 +1,87 @@ +# Copyright (c) 2010-2024 openpyxl + +from itertools import accumulate +import operator +import numpy +from openpyxl.compat.product import prod + + +def dataframe_to_rows(df, index=True, header=True): + """ + Convert a Pandas dataframe into something suitable for passing into a worksheet. + If index is True then the index will be included, starting one row below the header. + If header is True then column headers will be included starting one column to the right. + Formatting should be done by client code. + """ + from pandas import Timestamp + + if header: + if df.columns.nlevels > 1: + rows = expand_index(df.columns, header) + else: + rows = [list(df.columns.values)] + for row in rows: + n = [] + for v in row: + if isinstance(v, numpy.datetime64): + v = Timestamp(v) + n.append(v) + row = n + if index: + row = [None]*df.index.nlevels + row + yield row + + if index: + yield df.index.names + + expanded = ([v] for v in df.index) + if df.index.nlevels > 1: + expanded = expand_index(df.index) + + # Using the expanded index is preferable to df.itertuples(index=True) so that we have 'None' inserted where applicable + for (df_index, row) in zip(expanded, df.itertuples(index=False)): + row = list(row) + if index: + row = df_index + row + yield row + + +def expand_index(index, header=False): + """ + Expand axis or column Multiindex + For columns use header = True + For axes use header = False (default) + """ + + # For each element of the index, zip the members with the previous row + # If the 2 elements of the zipped list do not match, we can insert the new value into the row + # or if an earlier member was different, all later members should be added to the row + values = list(index.values) + previous_value = [None] * len(values[0]) + result = [] + + for value in values: + row = [None] * len(value) + + # Once there's a difference in member of an index with the prior index, we need to store all subsequent members in the row + prior_change = False + for idx, (current_index_member, previous_index_member) in enumerate(zip(value, previous_value)): + + if current_index_member != previous_index_member or prior_change: + row[idx] = current_index_member + prior_change = True + + previous_value = value + + # If this is for a row index, we're already returning a row so just yield + if not header: + yield row + else: + result.append(row) + + # If it's for a header, we need to transpose to get it in row order + # Example: result = [['A', 'A'], [None, 'B']] -> [['A', None], ['A', 'B']] + if header: + result = numpy.array(result).transpose().tolist() + for row in result: + yield row diff --git a/venv/Lib/site-packages/openpyxl/utils/datetime.py b/venv/Lib/site-packages/openpyxl/utils/datetime.py new file mode 100644 index 0000000..bf7e500 --- /dev/null +++ b/venv/Lib/site-packages/openpyxl/utils/datetime.py @@ -0,0 +1,140 @@ +# Copyright (c) 2010-2024 openpyxl + +"""Manage Excel date weirdness.""" + +# Python stdlib imports +import datetime +from math import isnan +import re + + +# constants +MAC_EPOCH = datetime.datetime(1904, 1, 1) +WINDOWS_EPOCH = datetime.datetime(1899, 12, 30) +CALENDAR_WINDOWS_1900 = 2415018.5 # Julian date of WINDOWS_EPOCH +CALENDAR_MAC_1904 = 2416480.5 # Julian date of MAC_EPOCH +CALENDAR_WINDOWS_1900 = WINDOWS_EPOCH +CALENDAR_MAC_1904 = MAC_EPOCH +SECS_PER_DAY = 86400 + +ISO_FORMAT = '%Y-%m-%dT%H:%M:%SZ' +ISO_REGEX = re.compile(r''' +(?P(?P\d{4})-(?P\d{2})-(?P\d{2}))?T? +(?P

%(title)s

+ +''' + +DOC_HEADER_EXTERNALCSS = '''\ + + + + + %(title)s + + + + +

%(title)s

+ +''' + +DOC_FOOTER = '''\ + + +''' + + +class HtmlFormatter(Formatter): + r""" + Format tokens as HTML 4 ```` tags. By default, the content is enclosed + in a ``
`` tag, itself wrapped in a ``
`` tag (but see the `nowrap` option). + The ``
``'s CSS class can be set by the `cssclass` option. + + If the `linenos` option is set to ``"table"``, the ``
`` is
+    additionally wrapped inside a ```` which has one row and two
+    cells: one containing the line numbers and one containing the code.
+    Example:
+
+    .. sourcecode:: html
+
+        
+
+ + +
+
1
+            2
+
+
def foo(bar):
+              pass
+            
+
+ + (whitespace added to improve clarity). + + A list of lines can be specified using the `hl_lines` option to make these + lines highlighted (as of Pygments 0.11). + + With the `full` option, a complete HTML 4 document is output, including + the style definitions inside a `` + + +
{code}
+ + +""" + +CONSOLE_SVG_FORMAT = """\ + + + + + + + + + {lines} + + + {chrome} + + {backgrounds} + + {matrix} + + + +""" + +_SVG_FONT_FAMILY = "Rich Fira Code" +_SVG_CLASSES_PREFIX = "rich-svg" diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_extension.py b/venv/Lib/site-packages/pip/_vendor/rich/_extension.py new file mode 100644 index 0000000..cbd6da9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_extension.py @@ -0,0 +1,10 @@ +from typing import Any + + +def load_ipython_extension(ip: Any) -> None: # pragma: no cover + # prevent circular import + from pip._vendor.rich.pretty import install + from pip._vendor.rich.traceback import install as tr_install + + install() + tr_install() diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_fileno.py b/venv/Lib/site-packages/pip/_vendor/rich/_fileno.py new file mode 100644 index 0000000..b17ee65 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_fileno.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import IO, Callable + + +def get_fileno(file_like: IO[str]) -> int | None: + """Get fileno() from a file, accounting for poorly implemented file-like objects. + + Args: + file_like (IO): A file-like object. + + Returns: + int | None: The result of fileno if available, or None if operation failed. + """ + fileno: Callable[[], int] | None = getattr(file_like, "fileno", None) + if fileno is not None: + try: + return fileno() + except Exception: + # `fileno` is documented as potentially raising a OSError + # Alas, from the issues, there are so many poorly implemented file-like objects, + # that `fileno()` can raise just about anything. + return None + return None diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_inspect.py b/venv/Lib/site-packages/pip/_vendor/rich/_inspect.py new file mode 100644 index 0000000..30446ce --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_inspect.py @@ -0,0 +1,270 @@ +from __future__ import absolute_import + +import inspect +from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature +from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union + +from .console import Group, RenderableType +from .control import escape_control_codes +from .highlighter import ReprHighlighter +from .jupyter import JupyterMixin +from .panel import Panel +from .pretty import Pretty +from .table import Table +from .text import Text, TextType + + +def _first_paragraph(doc: str) -> str: + """Get the first paragraph from a docstring.""" + paragraph, _, _ = doc.partition("\n\n") + return paragraph + + +class Inspect(JupyterMixin): + """A renderable to inspect any Python Object. + + Args: + obj (Any): An object to inspect. + title (str, optional): Title to display over inspect result, or None use type. Defaults to None. + help (bool, optional): Show full help text rather than just first paragraph. Defaults to False. + methods (bool, optional): Enable inspection of callables. Defaults to False. + docs (bool, optional): Also render doc strings. Defaults to True. + private (bool, optional): Show private attributes (beginning with underscore). Defaults to False. + dunder (bool, optional): Show attributes starting with double underscore. Defaults to False. + sort (bool, optional): Sort attributes alphabetically. Defaults to True. + all (bool, optional): Show all attributes. Defaults to False. + value (bool, optional): Pretty print value of object. Defaults to True. + """ + + def __init__( + self, + obj: Any, + *, + title: Optional[TextType] = None, + help: bool = False, + methods: bool = False, + docs: bool = True, + private: bool = False, + dunder: bool = False, + sort: bool = True, + all: bool = True, + value: bool = True, + ) -> None: + self.highlighter = ReprHighlighter() + self.obj = obj + self.title = title or self._make_title(obj) + if all: + methods = private = dunder = True + self.help = help + self.methods = methods + self.docs = docs or help + self.private = private or dunder + self.dunder = dunder + self.sort = sort + self.value = value + + def _make_title(self, obj: Any) -> Text: + """Make a default title.""" + title_str = ( + str(obj) + if (isclass(obj) or callable(obj) or ismodule(obj)) + else str(type(obj)) + ) + title_text = self.highlighter(title_str) + return title_text + + def __rich__(self) -> Panel: + return Panel.fit( + Group(*self._render()), + title=self.title, + border_style="scope.border", + padding=(0, 1), + ) + + def _get_signature(self, name: str, obj: Any) -> Optional[Text]: + """Get a signature for a callable.""" + try: + _signature = str(signature(obj)) + ":" + except ValueError: + _signature = "(...)" + except TypeError: + return None + + source_filename: Optional[str] = None + try: + source_filename = getfile(obj) + except (OSError, TypeError): + # OSError is raised if obj has no source file, e.g. when defined in REPL. + pass + + callable_name = Text(name, style="inspect.callable") + if source_filename: + callable_name.stylize(f"link file://{source_filename}") + signature_text = self.highlighter(_signature) + + qualname = name or getattr(obj, "__qualname__", name) + + # If obj is a module, there may be classes (which are callable) to display + if inspect.isclass(obj): + prefix = "class" + elif inspect.iscoroutinefunction(obj): + prefix = "async def" + else: + prefix = "def" + + qual_signature = Text.assemble( + (f"{prefix} ", f"inspect.{prefix.replace(' ', '_')}"), + (qualname, "inspect.callable"), + signature_text, + ) + + return qual_signature + + def _render(self) -> Iterable[RenderableType]: + """Render object.""" + + def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]: + key, (_error, value) = item + return (callable(value), key.strip("_").lower()) + + def safe_getattr(attr_name: str) -> Tuple[Any, Any]: + """Get attribute or any exception.""" + try: + return (None, getattr(obj, attr_name)) + except Exception as error: + return (error, None) + + obj = self.obj + keys = dir(obj) + total_items = len(keys) + if not self.dunder: + keys = [key for key in keys if not key.startswith("__")] + if not self.private: + keys = [key for key in keys if not key.startswith("_")] + not_shown_count = total_items - len(keys) + items = [(key, safe_getattr(key)) for key in keys] + if self.sort: + items.sort(key=sort_items) + + items_table = Table.grid(padding=(0, 1), expand=False) + items_table.add_column(justify="right") + add_row = items_table.add_row + highlighter = self.highlighter + + if callable(obj): + signature = self._get_signature("", obj) + if signature is not None: + yield signature + yield "" + + if self.docs: + _doc = self._get_formatted_doc(obj) + if _doc is not None: + doc_text = Text(_doc, style="inspect.help") + doc_text = highlighter(doc_text) + yield doc_text + yield "" + + if self.value and not (isclass(obj) or callable(obj) or ismodule(obj)): + yield Panel( + Pretty(obj, indent_guides=True, max_length=10, max_string=60), + border_style="inspect.value.border", + ) + yield "" + + for key, (error, value) in items: + key_text = Text.assemble( + ( + key, + "inspect.attr.dunder" if key.startswith("__") else "inspect.attr", + ), + (" =", "inspect.equals"), + ) + if error is not None: + warning = key_text.copy() + warning.stylize("inspect.error") + add_row(warning, highlighter(repr(error))) + continue + + if callable(value): + if not self.methods: + continue + + _signature_text = self._get_signature(key, value) + if _signature_text is None: + add_row(key_text, Pretty(value, highlighter=highlighter)) + else: + if self.docs: + docs = self._get_formatted_doc(value) + if docs is not None: + _signature_text.append("\n" if "\n" in docs else " ") + doc = highlighter(docs) + doc.stylize("inspect.doc") + _signature_text.append(doc) + + add_row(key_text, _signature_text) + else: + add_row(key_text, Pretty(value, highlighter=highlighter)) + if items_table.row_count: + yield items_table + elif not_shown_count: + yield Text.from_markup( + f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] " + f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." + ) + + def _get_formatted_doc(self, object_: Any) -> Optional[str]: + """ + Extract the docstring of an object, process it and returns it. + The processing consists in cleaning up the doctring's indentation, + taking only its 1st paragraph if `self.help` is not True, + and escape its control codes. + + Args: + object_ (Any): the object to get the docstring from. + + Returns: + Optional[str]: the processed docstring, or None if no docstring was found. + """ + docs = getdoc(object_) + if docs is None: + return None + docs = cleandoc(docs).strip() + if not self.help: + docs = _first_paragraph(docs) + return escape_control_codes(docs) + + +def get_object_types_mro(obj: Union[object, Type[Any]]) -> Tuple[type, ...]: + """Returns the MRO of an object's class, or of the object itself if it's a class.""" + if not hasattr(obj, "__mro__"): + # N.B. we cannot use `if type(obj) is type` here because it doesn't work with + # some types of classes, such as the ones that use abc.ABCMeta. + obj = type(obj) + return getattr(obj, "__mro__", ()) + + +def get_object_types_mro_as_strings(obj: object) -> Collection[str]: + """ + Returns the MRO of an object's class as full qualified names, or of the object itself if it's a class. + + Examples: + `object_types_mro_as_strings(JSONDecoder)` will return `['json.decoder.JSONDecoder', 'builtins.object']` + """ + return [ + f'{getattr(type_, "__module__", "")}.{getattr(type_, "__qualname__", "")}' + for type_ in get_object_types_mro(obj) + ] + + +def is_object_one_of_types( + obj: object, fully_qualified_types_names: Collection[str] +) -> bool: + """ + Returns `True` if the given object's class (or the object itself, if it's a class) has one of the + fully qualified names in its MRO. + """ + for type_name in get_object_types_mro_as_strings(obj): + if type_name in fully_qualified_types_names: + return True + return False diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_log_render.py b/venv/Lib/site-packages/pip/_vendor/rich/_log_render.py new file mode 100644 index 0000000..fc16c84 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_log_render.py @@ -0,0 +1,94 @@ +from datetime import datetime +from typing import Iterable, List, Optional, TYPE_CHECKING, Union, Callable + + +from .text import Text, TextType + +if TYPE_CHECKING: + from .console import Console, ConsoleRenderable, RenderableType + from .table import Table + +FormatTimeCallable = Callable[[datetime], Text] + + +class LogRender: + def __init__( + self, + show_time: bool = True, + show_level: bool = False, + show_path: bool = True, + time_format: Union[str, FormatTimeCallable] = "[%x %X]", + omit_repeated_times: bool = True, + level_width: Optional[int] = 8, + ) -> None: + self.show_time = show_time + self.show_level = show_level + self.show_path = show_path + self.time_format = time_format + self.omit_repeated_times = omit_repeated_times + self.level_width = level_width + self._last_time: Optional[Text] = None + + def __call__( + self, + console: "Console", + renderables: Iterable["ConsoleRenderable"], + log_time: Optional[datetime] = None, + time_format: Optional[Union[str, FormatTimeCallable]] = None, + level: TextType = "", + path: Optional[str] = None, + line_no: Optional[int] = None, + link_path: Optional[str] = None, + ) -> "Table": + from .containers import Renderables + from .table import Table + + output = Table.grid(padding=(0, 1)) + output.expand = True + if self.show_time: + output.add_column(style="log.time") + if self.show_level: + output.add_column(style="log.level", width=self.level_width) + output.add_column(ratio=1, style="log.message", overflow="fold") + if self.show_path and path: + output.add_column(style="log.path") + row: List["RenderableType"] = [] + if self.show_time: + log_time = log_time or console.get_datetime() + time_format = time_format or self.time_format + if callable(time_format): + log_time_display = time_format(log_time) + else: + log_time_display = Text(log_time.strftime(time_format)) + if log_time_display == self._last_time and self.omit_repeated_times: + row.append(Text(" " * len(log_time_display))) + else: + row.append(log_time_display) + self._last_time = log_time_display + if self.show_level: + row.append(level) + + row.append(Renderables(renderables)) + if self.show_path and path: + path_text = Text() + path_text.append( + path, style=f"link file://{link_path}" if link_path else "" + ) + if line_no: + path_text.append(":") + path_text.append( + f"{line_no}", + style=f"link file://{link_path}#{line_no}" if link_path else "", + ) + row.append(path_text) + + output.add_row(*row) + return output + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + + c = Console() + c.print("[on blue]Hello", justify="right") + c.log("[on blue]hello", justify="right") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_loop.py b/venv/Lib/site-packages/pip/_vendor/rich/_loop.py new file mode 100644 index 0000000..01c6caf --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_loop.py @@ -0,0 +1,43 @@ +from typing import Iterable, Tuple, TypeVar + +T = TypeVar("T") + + +def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for first value.""" + iter_values = iter(values) + try: + value = next(iter_values) + except StopIteration: + return + yield True, value + for value in iter_values: + yield False, value + + +def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + for value in iter_values: + yield False, previous_value + previous_value = value + yield True, previous_value + + +def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: + """Iterate and generate a tuple with a flag for first and last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + first = True + for value in iter_values: + yield first, False, previous_value + first = False + previous_value = value + yield first, True, previous_value diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_null_file.py b/venv/Lib/site-packages/pip/_vendor/rich/_null_file.py new file mode 100644 index 0000000..b659673 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_null_file.py @@ -0,0 +1,69 @@ +from types import TracebackType +from typing import IO, Iterable, Iterator, List, Optional, Type + + +class NullFile(IO[str]): + def close(self) -> None: + pass + + def isatty(self) -> bool: + return False + + def read(self, __n: int = 1) -> str: + return "" + + def readable(self) -> bool: + return False + + def readline(self, __limit: int = 1) -> str: + return "" + + def readlines(self, __hint: int = 1) -> List[str]: + return [] + + def seek(self, __offset: int, __whence: int = 1) -> int: + return 0 + + def seekable(self) -> bool: + return False + + def tell(self) -> int: + return 0 + + def truncate(self, __size: Optional[int] = 1) -> int: + return 0 + + def writable(self) -> bool: + return False + + def writelines(self, __lines: Iterable[str]) -> None: + pass + + def __next__(self) -> str: + return "" + + def __iter__(self) -> Iterator[str]: + return iter([""]) + + def __enter__(self) -> IO[str]: + pass + + def __exit__( + self, + __t: Optional[Type[BaseException]], + __value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> None: + pass + + def write(self, text: str) -> int: + return 0 + + def flush(self) -> None: + pass + + def fileno(self) -> int: + return -1 + + +NULL_FILE = NullFile() diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_palettes.py b/venv/Lib/site-packages/pip/_vendor/rich/_palettes.py new file mode 100644 index 0000000..3c748d3 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_palettes.py @@ -0,0 +1,309 @@ +from .palette import Palette + + +# Taken from https://en.wikipedia.org/wiki/ANSI_escape_code (Windows 10 column) +WINDOWS_PALETTE = Palette( + [ + (12, 12, 12), + (197, 15, 31), + (19, 161, 14), + (193, 156, 0), + (0, 55, 218), + (136, 23, 152), + (58, 150, 221), + (204, 204, 204), + (118, 118, 118), + (231, 72, 86), + (22, 198, 12), + (249, 241, 165), + (59, 120, 255), + (180, 0, 158), + (97, 214, 214), + (242, 242, 242), + ] +) + +# # The standard ansi colors (including bright variants) +STANDARD_PALETTE = Palette( + [ + (0, 0, 0), + (170, 0, 0), + (0, 170, 0), + (170, 85, 0), + (0, 0, 170), + (170, 0, 170), + (0, 170, 170), + (170, 170, 170), + (85, 85, 85), + (255, 85, 85), + (85, 255, 85), + (255, 255, 85), + (85, 85, 255), + (255, 85, 255), + (85, 255, 255), + (255, 255, 255), + ] +) + + +# The 256 color palette +EIGHT_BIT_PALETTE = Palette( + [ + (0, 0, 0), + (128, 0, 0), + (0, 128, 0), + (128, 128, 0), + (0, 0, 128), + (128, 0, 128), + (0, 128, 128), + (192, 192, 192), + (128, 128, 128), + (255, 0, 0), + (0, 255, 0), + (255, 255, 0), + (0, 0, 255), + (255, 0, 255), + (0, 255, 255), + (255, 255, 255), + (0, 0, 0), + (0, 0, 95), + (0, 0, 135), + (0, 0, 175), + (0, 0, 215), + (0, 0, 255), + (0, 95, 0), + (0, 95, 95), + (0, 95, 135), + (0, 95, 175), + (0, 95, 215), + (0, 95, 255), + (0, 135, 0), + (0, 135, 95), + (0, 135, 135), + (0, 135, 175), + (0, 135, 215), + (0, 135, 255), + (0, 175, 0), + (0, 175, 95), + (0, 175, 135), + (0, 175, 175), + (0, 175, 215), + (0, 175, 255), + (0, 215, 0), + (0, 215, 95), + (0, 215, 135), + (0, 215, 175), + (0, 215, 215), + (0, 215, 255), + (0, 255, 0), + (0, 255, 95), + (0, 255, 135), + (0, 255, 175), + (0, 255, 215), + (0, 255, 255), + (95, 0, 0), + (95, 0, 95), + (95, 0, 135), + (95, 0, 175), + (95, 0, 215), + (95, 0, 255), + (95, 95, 0), + (95, 95, 95), + (95, 95, 135), + (95, 95, 175), + (95, 95, 215), + (95, 95, 255), + (95, 135, 0), + (95, 135, 95), + (95, 135, 135), + (95, 135, 175), + (95, 135, 215), + (95, 135, 255), + (95, 175, 0), + (95, 175, 95), + (95, 175, 135), + (95, 175, 175), + (95, 175, 215), + (95, 175, 255), + (95, 215, 0), + (95, 215, 95), + (95, 215, 135), + (95, 215, 175), + (95, 215, 215), + (95, 215, 255), + (95, 255, 0), + (95, 255, 95), + (95, 255, 135), + (95, 255, 175), + (95, 255, 215), + (95, 255, 255), + (135, 0, 0), + (135, 0, 95), + (135, 0, 135), + (135, 0, 175), + (135, 0, 215), + (135, 0, 255), + (135, 95, 0), + (135, 95, 95), + (135, 95, 135), + (135, 95, 175), + (135, 95, 215), + (135, 95, 255), + (135, 135, 0), + (135, 135, 95), + (135, 135, 135), + (135, 135, 175), + (135, 135, 215), + (135, 135, 255), + (135, 175, 0), + (135, 175, 95), + (135, 175, 135), + (135, 175, 175), + (135, 175, 215), + (135, 175, 255), + (135, 215, 0), + (135, 215, 95), + (135, 215, 135), + (135, 215, 175), + (135, 215, 215), + (135, 215, 255), + (135, 255, 0), + (135, 255, 95), + (135, 255, 135), + (135, 255, 175), + (135, 255, 215), + (135, 255, 255), + (175, 0, 0), + (175, 0, 95), + (175, 0, 135), + (175, 0, 175), + (175, 0, 215), + (175, 0, 255), + (175, 95, 0), + (175, 95, 95), + (175, 95, 135), + (175, 95, 175), + (175, 95, 215), + (175, 95, 255), + (175, 135, 0), + (175, 135, 95), + (175, 135, 135), + (175, 135, 175), + (175, 135, 215), + (175, 135, 255), + (175, 175, 0), + (175, 175, 95), + (175, 175, 135), + (175, 175, 175), + (175, 175, 215), + (175, 175, 255), + (175, 215, 0), + (175, 215, 95), + (175, 215, 135), + (175, 215, 175), + (175, 215, 215), + (175, 215, 255), + (175, 255, 0), + (175, 255, 95), + (175, 255, 135), + (175, 255, 175), + (175, 255, 215), + (175, 255, 255), + (215, 0, 0), + (215, 0, 95), + (215, 0, 135), + (215, 0, 175), + (215, 0, 215), + (215, 0, 255), + (215, 95, 0), + (215, 95, 95), + (215, 95, 135), + (215, 95, 175), + (215, 95, 215), + (215, 95, 255), + (215, 135, 0), + (215, 135, 95), + (215, 135, 135), + (215, 135, 175), + (215, 135, 215), + (215, 135, 255), + (215, 175, 0), + (215, 175, 95), + (215, 175, 135), + (215, 175, 175), + (215, 175, 215), + (215, 175, 255), + (215, 215, 0), + (215, 215, 95), + (215, 215, 135), + (215, 215, 175), + (215, 215, 215), + (215, 215, 255), + (215, 255, 0), + (215, 255, 95), + (215, 255, 135), + (215, 255, 175), + (215, 255, 215), + (215, 255, 255), + (255, 0, 0), + (255, 0, 95), + (255, 0, 135), + (255, 0, 175), + (255, 0, 215), + (255, 0, 255), + (255, 95, 0), + (255, 95, 95), + (255, 95, 135), + (255, 95, 175), + (255, 95, 215), + (255, 95, 255), + (255, 135, 0), + (255, 135, 95), + (255, 135, 135), + (255, 135, 175), + (255, 135, 215), + (255, 135, 255), + (255, 175, 0), + (255, 175, 95), + (255, 175, 135), + (255, 175, 175), + (255, 175, 215), + (255, 175, 255), + (255, 215, 0), + (255, 215, 95), + (255, 215, 135), + (255, 215, 175), + (255, 215, 215), + (255, 215, 255), + (255, 255, 0), + (255, 255, 95), + (255, 255, 135), + (255, 255, 175), + (255, 255, 215), + (255, 255, 255), + (8, 8, 8), + (18, 18, 18), + (28, 28, 28), + (38, 38, 38), + (48, 48, 48), + (58, 58, 58), + (68, 68, 68), + (78, 78, 78), + (88, 88, 88), + (98, 98, 98), + (108, 108, 108), + (118, 118, 118), + (128, 128, 128), + (138, 138, 138), + (148, 148, 148), + (158, 158, 158), + (168, 168, 168), + (178, 178, 178), + (188, 188, 188), + (198, 198, 198), + (208, 208, 208), + (218, 218, 218), + (228, 228, 228), + (238, 238, 238), + ] +) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_pick.py b/venv/Lib/site-packages/pip/_vendor/rich/_pick.py new file mode 100644 index 0000000..4f6d8b2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_pick.py @@ -0,0 +1,17 @@ +from typing import Optional + + +def pick_bool(*values: Optional[bool]) -> bool: + """Pick the first non-none bool or return the last value. + + Args: + *values (bool): Any number of boolean or None values. + + Returns: + bool: First non-none boolean. + """ + assert values, "1 or more values required" + for value in values: + if value is not None: + return value + return bool(value) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_ratio.py b/venv/Lib/site-packages/pip/_vendor/rich/_ratio.py new file mode 100644 index 0000000..95267b0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_ratio.py @@ -0,0 +1,159 @@ +import sys +from fractions import Fraction +from math import ceil +from typing import cast, List, Optional, Sequence + +if sys.version_info >= (3, 8): + from typing import Protocol +else: + from pip._vendor.typing_extensions import Protocol # pragma: no cover + + +class Edge(Protocol): + """Any object that defines an edge (such as Layout).""" + + size: Optional[int] = None + ratio: int = 1 + minimum_size: int = 1 + + +def ratio_resolve(total: int, edges: Sequence[Edge]) -> List[int]: + """Divide total space to satisfy size, ratio, and minimum_size, constraints. + + The returned list of integers should add up to total in most cases, unless it is + impossible to satisfy all the constraints. For instance, if there are two edges + with a minimum size of 20 each and `total` is 30 then the returned list will be + greater than total. In practice, this would mean that a Layout object would + clip the rows that would overflow the screen height. + + Args: + total (int): Total number of characters. + edges (List[Edge]): Edges within total space. + + Returns: + List[int]: Number of characters for each edge. + """ + # Size of edge or None for yet to be determined + sizes = [(edge.size or None) for edge in edges] + + _Fraction = Fraction + + # While any edges haven't been calculated + while None in sizes: + # Get flexible edges and index to map these back on to sizes list + flexible_edges = [ + (index, edge) + for index, (size, edge) in enumerate(zip(sizes, edges)) + if size is None + ] + # Remaining space in total + remaining = total - sum(size or 0 for size in sizes) + if remaining <= 0: + # No room for flexible edges + return [ + ((edge.minimum_size or 1) if size is None else size) + for size, edge in zip(sizes, edges) + ] + # Calculate number of characters in a ratio portion + portion = _Fraction( + remaining, sum((edge.ratio or 1) for _, edge in flexible_edges) + ) + + # If any edges will be less than their minimum, replace size with the minimum + for index, edge in flexible_edges: + if portion * edge.ratio <= edge.minimum_size: + sizes[index] = edge.minimum_size + # New fixed size will invalidate calculations, so we need to repeat the process + break + else: + # Distribute flexible space and compensate for rounding error + # Since edge sizes can only be integers we need to add the remainder + # to the following line + remainder = _Fraction(0) + for index, edge in flexible_edges: + size, remainder = divmod(portion * edge.ratio + remainder, 1) + sizes[index] = size + break + # Sizes now contains integers only + return cast(List[int], sizes) + + +def ratio_reduce( + total: int, ratios: List[int], maximums: List[int], values: List[int] +) -> List[int]: + """Divide an integer total in to parts based on ratios. + + Args: + total (int): The total to divide. + ratios (List[int]): A list of integer ratios. + maximums (List[int]): List of maximums values for each slot. + values (List[int]): List of values + + Returns: + List[int]: A list of integers guaranteed to sum to total. + """ + ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)] + total_ratio = sum(ratios) + if not total_ratio: + return values[:] + total_remaining = total + result: List[int] = [] + append = result.append + for ratio, maximum, value in zip(ratios, maximums, values): + if ratio and total_ratio > 0: + distributed = min(maximum, round(ratio * total_remaining / total_ratio)) + append(value - distributed) + total_remaining -= distributed + total_ratio -= ratio + else: + append(value) + return result + + +def ratio_distribute( + total: int, ratios: List[int], minimums: Optional[List[int]] = None +) -> List[int]: + """Distribute an integer total in to parts based on ratios. + + Args: + total (int): The total to divide. + ratios (List[int]): A list of integer ratios. + minimums (List[int]): List of minimum values for each slot. + + Returns: + List[int]: A list of integers guaranteed to sum to total. + """ + if minimums: + ratios = [ratio if _min else 0 for ratio, _min in zip(ratios, minimums)] + total_ratio = sum(ratios) + assert total_ratio > 0, "Sum of ratios must be > 0" + + total_remaining = total + distributed_total: List[int] = [] + append = distributed_total.append + if minimums is None: + _minimums = [0] * len(ratios) + else: + _minimums = minimums + for ratio, minimum in zip(ratios, _minimums): + if total_ratio > 0: + distributed = max(minimum, ceil(ratio * total_remaining / total_ratio)) + else: + distributed = total_remaining + append(distributed) + total_ratio -= ratio + total_remaining -= distributed + return distributed_total + + +if __name__ == "__main__": + from dataclasses import dataclass + + @dataclass + class E: + size: Optional[int] = None + ratio: int = 1 + minimum_size: int = 1 + + resolved = ratio_resolve(110, [E(None, 1, 1), E(None, 1, 1), E(None, 1, 1)]) + print(sum(resolved)) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_spinners.py b/venv/Lib/site-packages/pip/_vendor/rich/_spinners.py new file mode 100644 index 0000000..d0bb1fe --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_spinners.py @@ -0,0 +1,482 @@ +""" +Spinners are from: +* cli-spinners: + MIT License + Copyright (c) Sindre Sorhus (sindresorhus.com) + 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. +""" + +SPINNERS = { + "dots": { + "interval": 80, + "frames": "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", + }, + "dots2": {"interval": 80, "frames": "⣾⣽⣻⢿⡿⣟⣯⣷"}, + "dots3": { + "interval": 80, + "frames": "⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓", + }, + "dots4": { + "interval": 80, + "frames": "⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆", + }, + "dots5": { + "interval": 80, + "frames": "⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋", + }, + "dots6": { + "interval": 80, + "frames": "⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁", + }, + "dots7": { + "interval": 80, + "frames": "⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈", + }, + "dots8": { + "interval": 80, + "frames": "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈", + }, + "dots9": {"interval": 80, "frames": "⢹⢺⢼⣸⣇⡧⡗⡏"}, + "dots10": {"interval": 80, "frames": "⢄⢂⢁⡁⡈⡐⡠"}, + "dots11": {"interval": 100, "frames": "⠁⠂⠄⡀⢀⠠⠐⠈"}, + "dots12": { + "interval": 80, + "frames": [ + "⢀⠀", + "⡀⠀", + "⠄⠀", + "⢂⠀", + "⡂⠀", + "⠅⠀", + "⢃⠀", + "⡃⠀", + "⠍⠀", + "⢋⠀", + "⡋⠀", + "⠍⠁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⢈⠩", + "⡀⢙", + "⠄⡙", + "⢂⠩", + "⡂⢘", + "⠅⡘", + "⢃⠨", + "⡃⢐", + "⠍⡐", + "⢋⠠", + "⡋⢀", + "⠍⡁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⠈⠩", + "⠀⢙", + "⠀⡙", + "⠀⠩", + "⠀⢘", + "⠀⡘", + "⠀⠨", + "⠀⢐", + "⠀⡐", + "⠀⠠", + "⠀⢀", + "⠀⡀", + ], + }, + "dots8Bit": { + "interval": 80, + "frames": "⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙" + "⡚⡛⡜⡝⡞⡟⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻" + "⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕" + "⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷" + "⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿", + }, + "line": {"interval": 130, "frames": ["-", "\\", "|", "/"]}, + "line2": {"interval": 100, "frames": "⠂-–—–-"}, + "pipe": {"interval": 100, "frames": "┤┘┴└├┌┬┐"}, + "simpleDots": {"interval": 400, "frames": [". ", ".. ", "...", " "]}, + "simpleDotsScrolling": { + "interval": 200, + "frames": [". ", ".. ", "...", " ..", " .", " "], + }, + "star": {"interval": 70, "frames": "✶✸✹✺✹✷"}, + "star2": {"interval": 80, "frames": "+x*"}, + "flip": { + "interval": 70, + "frames": "___-``'´-___", + }, + "hamburger": {"interval": 100, "frames": "☱☲☴"}, + "growVertical": { + "interval": 120, + "frames": "▁▃▄▅▆▇▆▅▄▃", + }, + "growHorizontal": { + "interval": 120, + "frames": "▏▎▍▌▋▊▉▊▋▌▍▎", + }, + "balloon": {"interval": 140, "frames": " .oO@* "}, + "balloon2": {"interval": 120, "frames": ".oO°Oo."}, + "noise": {"interval": 100, "frames": "▓▒░"}, + "bounce": {"interval": 120, "frames": "⠁⠂⠄⠂"}, + "boxBounce": {"interval": 120, "frames": "▖▘▝▗"}, + "boxBounce2": {"interval": 100, "frames": "▌▀▐▄"}, + "triangle": {"interval": 50, "frames": "◢◣◤◥"}, + "arc": {"interval": 100, "frames": "◜◠◝◞◡◟"}, + "circle": {"interval": 120, "frames": "◡⊙◠"}, + "squareCorners": {"interval": 180, "frames": "◰◳◲◱"}, + "circleQuarters": {"interval": 120, "frames": "◴◷◶◵"}, + "circleHalves": {"interval": 50, "frames": "◐◓◑◒"}, + "squish": {"interval": 100, "frames": "╫╪"}, + "toggle": {"interval": 250, "frames": "⊶⊷"}, + "toggle2": {"interval": 80, "frames": "▫▪"}, + "toggle3": {"interval": 120, "frames": "□■"}, + "toggle4": {"interval": 100, "frames": "■□▪▫"}, + "toggle5": {"interval": 100, "frames": "▮▯"}, + "toggle6": {"interval": 300, "frames": "ဝ၀"}, + "toggle7": {"interval": 80, "frames": "⦾⦿"}, + "toggle8": {"interval": 100, "frames": "◍◌"}, + "toggle9": {"interval": 100, "frames": "◉◎"}, + "toggle10": {"interval": 100, "frames": "㊂㊀㊁"}, + "toggle11": {"interval": 50, "frames": "⧇⧆"}, + "toggle12": {"interval": 120, "frames": "☗☖"}, + "toggle13": {"interval": 80, "frames": "=*-"}, + "arrow": {"interval": 100, "frames": "←↖↑↗→↘↓↙"}, + "arrow2": { + "interval": 80, + "frames": ["⬆️ ", "↗️ ", "➡️ ", "↘️ ", "⬇️ ", "↙️ ", "⬅️ ", "↖️ "], + }, + "arrow3": { + "interval": 120, + "frames": ["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"], + }, + "bouncingBar": { + "interval": 80, + "frames": [ + "[ ]", + "[= ]", + "[== ]", + "[=== ]", + "[ ===]", + "[ ==]", + "[ =]", + "[ ]", + "[ =]", + "[ ==]", + "[ ===]", + "[====]", + "[=== ]", + "[== ]", + "[= ]", + ], + }, + "bouncingBall": { + "interval": 80, + "frames": [ + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "( ●)", + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "(● )", + ], + }, + "smiley": {"interval": 200, "frames": ["😄 ", "😝 "]}, + "monkey": {"interval": 300, "frames": ["🙈 ", "🙈 ", "🙉 ", "🙊 "]}, + "hearts": {"interval": 100, "frames": ["💛 ", "💙 ", "💜 ", "💚 ", "❤️ "]}, + "clock": { + "interval": 100, + "frames": [ + "🕛 ", + "🕐 ", + "🕑 ", + "🕒 ", + "🕓 ", + "🕔 ", + "🕕 ", + "🕖 ", + "🕗 ", + "🕘 ", + "🕙 ", + "🕚 ", + ], + }, + "earth": {"interval": 180, "frames": ["🌍 ", "🌎 ", "🌏 "]}, + "material": { + "interval": 17, + "frames": [ + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███████▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "██████████▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "█████████████▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁██████████████▁▁▁▁", + "▁▁▁██████████████▁▁▁", + "▁▁▁▁█████████████▁▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁▁▁████████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁▁█████████████▁▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁▁███████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁▁█████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + ], + }, + "moon": { + "interval": 80, + "frames": ["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "], + }, + "runner": {"interval": 140, "frames": ["🚶 ", "🏃 "]}, + "pong": { + "interval": 80, + "frames": [ + "▐⠂ ▌", + "▐⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂▌", + "▐ ⠠▌", + "▐ ⡀▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐⠠ ▌", + ], + }, + "shark": { + "interval": 120, + "frames": [ + "▐|\\____________▌", + "▐_|\\___________▌", + "▐__|\\__________▌", + "▐___|\\_________▌", + "▐____|\\________▌", + "▐_____|\\_______▌", + "▐______|\\______▌", + "▐_______|\\_____▌", + "▐________|\\____▌", + "▐_________|\\___▌", + "▐__________|\\__▌", + "▐___________|\\_▌", + "▐____________|\\▌", + "▐____________/|▌", + "▐___________/|_▌", + "▐__________/|__▌", + "▐_________/|___▌", + "▐________/|____▌", + "▐_______/|_____▌", + "▐______/|______▌", + "▐_____/|_______▌", + "▐____/|________▌", + "▐___/|_________▌", + "▐__/|__________▌", + "▐_/|___________▌", + "▐/|____________▌", + ], + }, + "dqpb": {"interval": 100, "frames": "dqpb"}, + "weather": { + "interval": 100, + "frames": [ + "☀️ ", + "☀️ ", + "☀️ ", + "🌤 ", + "⛅️ ", + "🌥 ", + "☁️ ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "⛈ ", + "🌨 ", + "🌧 ", + "🌨 ", + "☁️ ", + "🌥 ", + "⛅️ ", + "🌤 ", + "☀️ ", + "☀️ ", + ], + }, + "christmas": {"interval": 400, "frames": "🌲🎄"}, + "grenade": { + "interval": 80, + "frames": [ + "، ", + "′ ", + " ´ ", + " ‾ ", + " ⸌", + " ⸊", + " |", + " ⁎", + " ⁕", + " ෴ ", + " ⁓", + " ", + " ", + " ", + ], + }, + "point": {"interval": 125, "frames": ["∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"]}, + "layer": {"interval": 150, "frames": "-=≡"}, + "betaWave": { + "interval": 80, + "frames": [ + "ρββββββ", + "βρβββββ", + "ββρββββ", + "βββρβββ", + "ββββρββ", + "βββββρβ", + "ββββββρ", + ], + }, + "aesthetic": { + "interval": 80, + "frames": [ + "▰▱▱▱▱▱▱", + "▰▰▱▱▱▱▱", + "▰▰▰▱▱▱▱", + "▰▰▰▰▱▱▱", + "▰▰▰▰▰▱▱", + "▰▰▰▰▰▰▱", + "▰▰▰▰▰▰▰", + "▰▱▱▱▱▱▱", + ], + }, +} diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_stack.py b/venv/Lib/site-packages/pip/_vendor/rich/_stack.py new file mode 100644 index 0000000..194564e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_stack.py @@ -0,0 +1,16 @@ +from typing import List, TypeVar + +T = TypeVar("T") + + +class Stack(List[T]): + """A small shim over builtin list.""" + + @property + def top(self) -> T: + """Get top of stack.""" + return self[-1] + + def push(self, item: T) -> None: + """Push an item on to the stack (append in stack nomenclature).""" + self.append(item) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_timer.py b/venv/Lib/site-packages/pip/_vendor/rich/_timer.py new file mode 100644 index 0000000..a2ca6be --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_timer.py @@ -0,0 +1,19 @@ +""" +Timer context manager, only used in debug. + +""" + +from time import time + +import contextlib +from typing import Generator + + +@contextlib.contextmanager +def timer(subject: str = "time") -> Generator[None, None, None]: + """print the elapsed time. (only used in debugging)""" + start = time() + yield + elapsed = time() - start + elapsed_ms = elapsed * 1000 + print(f"{subject} elapsed {elapsed_ms:.1f}ms") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py b/venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py new file mode 100644 index 0000000..81b1082 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py @@ -0,0 +1,662 @@ +"""Light wrapper around the Win32 Console API - this module should only be imported on Windows + +The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions +""" +import ctypes +import sys +from typing import Any + +windll: Any = None +if sys.platform == "win32": + windll = ctypes.LibraryLoader(ctypes.WinDLL) +else: + raise ImportError(f"{__name__} can only be imported on Windows") + +import time +from ctypes import Structure, byref, wintypes +from typing import IO, NamedTuple, Type, cast + +from pip._vendor.rich.color import ColorSystem +from pip._vendor.rich.style import Style + +STDOUT = -11 +ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4 + +COORD = wintypes._COORD + + +class LegacyWindowsError(Exception): + pass + + +class WindowsCoordinates(NamedTuple): + """Coordinates in the Windows Console API are (y, x), not (x, y). + This class is intended to prevent that confusion. + Rows and columns are indexed from 0. + This class can be used in place of wintypes._COORD in arguments and argtypes. + """ + + row: int + col: int + + @classmethod + def from_param(cls, value: "WindowsCoordinates") -> COORD: + """Converts a WindowsCoordinates into a wintypes _COORD structure. + This classmethod is internally called by ctypes to perform the conversion. + + Args: + value (WindowsCoordinates): The input coordinates to convert. + + Returns: + wintypes._COORD: The converted coordinates struct. + """ + return COORD(value.col, value.row) + + +class CONSOLE_SCREEN_BUFFER_INFO(Structure): + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + + +class CONSOLE_CURSOR_INFO(ctypes.Structure): + _fields_ = [("dwSize", wintypes.DWORD), ("bVisible", wintypes.BOOL)] + + +_GetStdHandle = windll.kernel32.GetStdHandle +_GetStdHandle.argtypes = [ + wintypes.DWORD, +] +_GetStdHandle.restype = wintypes.HANDLE + + +def GetStdHandle(handle: int = STDOUT) -> wintypes.HANDLE: + """Retrieves a handle to the specified standard device (standard input, standard output, or standard error). + + Args: + handle (int): Integer identifier for the handle. Defaults to -11 (stdout). + + Returns: + wintypes.HANDLE: The handle + """ + return cast(wintypes.HANDLE, _GetStdHandle(handle)) + + +_GetConsoleMode = windll.kernel32.GetConsoleMode +_GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] +_GetConsoleMode.restype = wintypes.BOOL + + +def GetConsoleMode(std_handle: wintypes.HANDLE) -> int: + """Retrieves the current input mode of a console's input buffer + or the current output mode of a console screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + + Raises: + LegacyWindowsError: If any error occurs while calling the Windows console API. + + Returns: + int: Value representing the current console mode as documented at + https://docs.microsoft.com/en-us/windows/console/getconsolemode#parameters + """ + + console_mode = wintypes.DWORD() + success = bool(_GetConsoleMode(std_handle, console_mode)) + if not success: + raise LegacyWindowsError("Unable to get legacy Windows Console Mode") + return console_mode.value + + +_FillConsoleOutputCharacterW = windll.kernel32.FillConsoleOutputCharacterW +_FillConsoleOutputCharacterW.argtypes = [ + wintypes.HANDLE, + ctypes.c_char, + wintypes.DWORD, + cast(Type[COORD], WindowsCoordinates), + ctypes.POINTER(wintypes.DWORD), +] +_FillConsoleOutputCharacterW.restype = wintypes.BOOL + + +def FillConsoleOutputCharacter( + std_handle: wintypes.HANDLE, + char: str, + length: int, + start: WindowsCoordinates, +) -> int: + """Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + char (str): The character to write. Must be a string of length 1. + length (int): The number of times to write the character. + start (WindowsCoordinates): The coordinates to start writing at. + + Returns: + int: The number of characters written. + """ + character = ctypes.c_char(char.encode()) + num_characters = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + _FillConsoleOutputCharacterW( + std_handle, + character, + num_characters, + start, + byref(num_written), + ) + return num_written.value + + +_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute +_FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + cast(Type[COORD], WindowsCoordinates), + ctypes.POINTER(wintypes.DWORD), +] +_FillConsoleOutputAttribute.restype = wintypes.BOOL + + +def FillConsoleOutputAttribute( + std_handle: wintypes.HANDLE, + attributes: int, + length: int, + start: WindowsCoordinates, +) -> int: + """Sets the character attributes for a specified number of character cells, + beginning at the specified coordinates in a screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + attributes (int): Integer value representing the foreground and background colours of the cells. + length (int): The number of cells to set the output attribute of. + start (WindowsCoordinates): The coordinates of the first cell whose attributes are to be set. + + Returns: + int: The number of cells whose attributes were actually set. + """ + num_cells = wintypes.DWORD(length) + style_attrs = wintypes.WORD(attributes) + num_written = wintypes.DWORD(0) + _FillConsoleOutputAttribute( + std_handle, style_attrs, num_cells, start, byref(num_written) + ) + return num_written.value + + +_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute +_SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, +] +_SetConsoleTextAttribute.restype = wintypes.BOOL + + +def SetConsoleTextAttribute( + std_handle: wintypes.HANDLE, attributes: wintypes.WORD +) -> bool: + """Set the colour attributes for all text written after this function is called. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + attributes (int): Integer value representing the foreground and background colours. + + + Returns: + bool: True if the attribute was set successfully, otherwise False. + """ + return bool(_SetConsoleTextAttribute(std_handle, attributes)) + + +_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo +_GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO), +] +_GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + +def GetConsoleScreenBufferInfo( + std_handle: wintypes.HANDLE, +) -> CONSOLE_SCREEN_BUFFER_INFO: + """Retrieves information about the specified console screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + + Returns: + CONSOLE_SCREEN_BUFFER_INFO: A CONSOLE_SCREEN_BUFFER_INFO ctype struct contain information about + screen size, cursor position, colour attributes, and more.""" + console_screen_buffer_info = CONSOLE_SCREEN_BUFFER_INFO() + _GetConsoleScreenBufferInfo(std_handle, byref(console_screen_buffer_info)) + return console_screen_buffer_info + + +_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition +_SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + cast(Type[COORD], WindowsCoordinates), +] +_SetConsoleCursorPosition.restype = wintypes.BOOL + + +def SetConsoleCursorPosition( + std_handle: wintypes.HANDLE, coords: WindowsCoordinates +) -> bool: + """Set the position of the cursor in the console screen + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + coords (WindowsCoordinates): The coordinates to move the cursor to. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleCursorPosition(std_handle, coords)) + + +_GetConsoleCursorInfo = windll.kernel32.GetConsoleCursorInfo +_GetConsoleCursorInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_CURSOR_INFO), +] +_GetConsoleCursorInfo.restype = wintypes.BOOL + + +def GetConsoleCursorInfo( + std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO +) -> bool: + """Get the cursor info - used to get cursor visibility and width + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct that receives information + about the console's cursor. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_GetConsoleCursorInfo(std_handle, byref(cursor_info))) + + +_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo +_SetConsoleCursorInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_CURSOR_INFO), +] +_SetConsoleCursorInfo.restype = wintypes.BOOL + + +def SetConsoleCursorInfo( + std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO +) -> bool: + """Set the cursor info - used for adjusting cursor visibility and width + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct containing the new cursor info. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleCursorInfo(std_handle, byref(cursor_info))) + + +_SetConsoleTitle = windll.kernel32.SetConsoleTitleW +_SetConsoleTitle.argtypes = [wintypes.LPCWSTR] +_SetConsoleTitle.restype = wintypes.BOOL + + +def SetConsoleTitle(title: str) -> bool: + """Sets the title of the current console window + + Args: + title (str): The new title of the console window. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleTitle(title)) + + +class LegacyWindowsTerm: + """This class allows interaction with the legacy Windows Console API. It should only be used in the context + of environments where virtual terminal processing is not available. However, if it is used in a Windows environment, + the entire API should work. + + Args: + file (IO[str]): The file which the Windows Console API HANDLE is retrieved from, defaults to sys.stdout. + """ + + BRIGHT_BIT = 8 + + # Indices are ANSI color numbers, values are the corresponding Windows Console API color numbers + ANSI_TO_WINDOWS = [ + 0, # black The Windows colours are defined in wincon.h as follows: + 4, # red define FOREGROUND_BLUE 0x0001 -- 0000 0001 + 2, # green define FOREGROUND_GREEN 0x0002 -- 0000 0010 + 6, # yellow define FOREGROUND_RED 0x0004 -- 0000 0100 + 1, # blue define FOREGROUND_INTENSITY 0x0008 -- 0000 1000 + 5, # magenta define BACKGROUND_BLUE 0x0010 -- 0001 0000 + 3, # cyan define BACKGROUND_GREEN 0x0020 -- 0010 0000 + 7, # white define BACKGROUND_RED 0x0040 -- 0100 0000 + 8, # bright black (grey) define BACKGROUND_INTENSITY 0x0080 -- 1000 0000 + 12, # bright red + 10, # bright green + 14, # bright yellow + 9, # bright blue + 13, # bright magenta + 11, # bright cyan + 15, # bright white + ] + + def __init__(self, file: "IO[str]") -> None: + handle = GetStdHandle(STDOUT) + self._handle = handle + default_text = GetConsoleScreenBufferInfo(handle).wAttributes + self._default_text = default_text + + self._default_fore = default_text & 7 + self._default_back = (default_text >> 4) & 7 + self._default_attrs = self._default_fore | (self._default_back << 4) + + self._file = file + self.write = file.write + self.flush = file.flush + + @property + def cursor_position(self) -> WindowsCoordinates: + """Returns the current position of the cursor (0-based) + + Returns: + WindowsCoordinates: The current cursor position. + """ + coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition + return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X)) + + @property + def screen_size(self) -> WindowsCoordinates: + """Returns the current size of the console screen buffer, in character columns and rows + + Returns: + WindowsCoordinates: The width and height of the screen as WindowsCoordinates. + """ + screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize + return WindowsCoordinates( + row=cast(int, screen_size.Y), col=cast(int, screen_size.X) + ) + + def write_text(self, text: str) -> None: + """Write text directly to the terminal without any modification of styles + + Args: + text (str): The text to write to the console + """ + self.write(text) + self.flush() + + def write_styled(self, text: str, style: Style) -> None: + """Write styled text to the terminal. + + Args: + text (str): The text to write + style (Style): The style of the text + """ + color = style.color + bgcolor = style.bgcolor + if style.reverse: + color, bgcolor = bgcolor, color + + if color: + fore = color.downgrade(ColorSystem.WINDOWS).number + fore = fore if fore is not None else 7 # Default to ANSI 7: White + if style.bold: + fore = fore | self.BRIGHT_BIT + if style.dim: + fore = fore & ~self.BRIGHT_BIT + fore = self.ANSI_TO_WINDOWS[fore] + else: + fore = self._default_fore + + if bgcolor: + back = bgcolor.downgrade(ColorSystem.WINDOWS).number + back = back if back is not None else 0 # Default to ANSI 0: Black + back = self.ANSI_TO_WINDOWS[back] + else: + back = self._default_back + + assert fore is not None + assert back is not None + + SetConsoleTextAttribute( + self._handle, attributes=ctypes.c_ushort(fore | (back << 4)) + ) + self.write_text(text) + SetConsoleTextAttribute(self._handle, attributes=self._default_text) + + def move_cursor_to(self, new_position: WindowsCoordinates) -> None: + """Set the position of the cursor + + Args: + new_position (WindowsCoordinates): The WindowsCoordinates representing the new position of the cursor. + """ + if new_position.col < 0 or new_position.row < 0: + return + SetConsoleCursorPosition(self._handle, coords=new_position) + + def erase_line(self) -> None: + """Erase all content on the line the cursor is currently located at""" + screen_size = self.screen_size + cursor_position = self.cursor_position + cells_to_erase = screen_size.col + start_coordinates = WindowsCoordinates(row=cursor_position.row, col=0) + FillConsoleOutputCharacter( + self._handle, " ", length=cells_to_erase, start=start_coordinates + ) + FillConsoleOutputAttribute( + self._handle, + self._default_attrs, + length=cells_to_erase, + start=start_coordinates, + ) + + def erase_end_of_line(self) -> None: + """Erase all content from the cursor position to the end of that line""" + cursor_position = self.cursor_position + cells_to_erase = self.screen_size.col - cursor_position.col + FillConsoleOutputCharacter( + self._handle, " ", length=cells_to_erase, start=cursor_position + ) + FillConsoleOutputAttribute( + self._handle, + self._default_attrs, + length=cells_to_erase, + start=cursor_position, + ) + + def erase_start_of_line(self) -> None: + """Erase all content from the cursor position to the start of that line""" + row, col = self.cursor_position + start = WindowsCoordinates(row, 0) + FillConsoleOutputCharacter(self._handle, " ", length=col, start=start) + FillConsoleOutputAttribute( + self._handle, self._default_attrs, length=col, start=start + ) + + def move_cursor_up(self) -> None: + """Move the cursor up a single cell""" + cursor_position = self.cursor_position + SetConsoleCursorPosition( + self._handle, + coords=WindowsCoordinates( + row=cursor_position.row - 1, col=cursor_position.col + ), + ) + + def move_cursor_down(self) -> None: + """Move the cursor down a single cell""" + cursor_position = self.cursor_position + SetConsoleCursorPosition( + self._handle, + coords=WindowsCoordinates( + row=cursor_position.row + 1, + col=cursor_position.col, + ), + ) + + def move_cursor_forward(self) -> None: + """Move the cursor forward a single cell. Wrap to the next line if required.""" + row, col = self.cursor_position + if col == self.screen_size.col - 1: + row += 1 + col = 0 + else: + col += 1 + SetConsoleCursorPosition( + self._handle, coords=WindowsCoordinates(row=row, col=col) + ) + + def move_cursor_to_column(self, column: int) -> None: + """Move cursor to the column specified by the zero-based column index, staying on the same row + + Args: + column (int): The zero-based column index to move the cursor to. + """ + row, _ = self.cursor_position + SetConsoleCursorPosition(self._handle, coords=WindowsCoordinates(row, column)) + + def move_cursor_backward(self) -> None: + """Move the cursor backward a single cell. Wrap to the previous line if required.""" + row, col = self.cursor_position + if col == 0: + row -= 1 + col = self.screen_size.col - 1 + else: + col -= 1 + SetConsoleCursorPosition( + self._handle, coords=WindowsCoordinates(row=row, col=col) + ) + + def hide_cursor(self) -> None: + """Hide the cursor""" + current_cursor_size = self._get_cursor_size() + invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0) + SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor) + + def show_cursor(self) -> None: + """Show the cursor""" + current_cursor_size = self._get_cursor_size() + visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1) + SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor) + + def set_title(self, title: str) -> None: + """Set the title of the terminal window + + Args: + title (str): The new title of the console window + """ + assert len(title) < 255, "Console title must be less than 255 characters" + SetConsoleTitle(title) + + def _get_cursor_size(self) -> int: + """Get the percentage of the character cell that is filled by the cursor""" + cursor_info = CONSOLE_CURSOR_INFO() + GetConsoleCursorInfo(self._handle, cursor_info=cursor_info) + return int(cursor_info.dwSize) + + +if __name__ == "__main__": + handle = GetStdHandle() + + from pip._vendor.rich.console import Console + + console = Console() + + term = LegacyWindowsTerm(sys.stdout) + term.set_title("Win32 Console Examples") + + style = Style(color="black", bgcolor="red") + + heading = Style.parse("black on green") + + # Check colour output + console.rule("Checking colour output") + console.print("[on red]on red!") + console.print("[blue]blue!") + console.print("[yellow]yellow!") + console.print("[bold yellow]bold yellow!") + console.print("[bright_yellow]bright_yellow!") + console.print("[dim bright_yellow]dim bright_yellow!") + console.print("[italic cyan]italic cyan!") + console.print("[bold white on blue]bold white on blue!") + console.print("[reverse bold white on blue]reverse bold white on blue!") + console.print("[bold black on cyan]bold black on cyan!") + console.print("[black on green]black on green!") + console.print("[blue on green]blue on green!") + console.print("[white on black]white on black!") + console.print("[black on white]black on white!") + console.print("[#1BB152 on #DA812D]#1BB152 on #DA812D!") + + # Check cursor movement + console.rule("Checking cursor movement") + console.print() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("went back and wrapped to prev line") + time.sleep(1) + term.move_cursor_up() + term.write_text("we go up") + time.sleep(1) + term.move_cursor_down() + term.write_text("and down") + time.sleep(1) + term.move_cursor_up() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("we went up and back 2") + time.sleep(1) + term.move_cursor_down() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("we went down and back 2") + time.sleep(1) + + # Check erasing of lines + term.hide_cursor() + console.print() + console.rule("Checking line erasing") + console.print("\n...Deleting to the start of the line...") + term.write_text("The red arrow shows the cursor location, and direction of erase") + time.sleep(1) + term.move_cursor_to_column(16) + term.write_styled("<", Style.parse("black on red")) + term.move_cursor_backward() + time.sleep(1) + term.erase_start_of_line() + time.sleep(1) + + console.print("\n\n...And to the end of the line...") + term.write_text("The red arrow shows the cursor location, and direction of erase") + time.sleep(1) + + term.move_cursor_to_column(16) + term.write_styled(">", Style.parse("black on red")) + time.sleep(1) + term.erase_end_of_line() + time.sleep(1) + + console.print("\n\n...Now the whole line will be erased...") + term.write_styled("I'm going to disappear!", style=Style.parse("black on cyan")) + time.sleep(1) + term.erase_line() + + term.show_cursor() + print("\n") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_windows.py b/venv/Lib/site-packages/pip/_vendor/rich/_windows.py new file mode 100644 index 0000000..7520a9f --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_windows.py @@ -0,0 +1,71 @@ +import sys +from dataclasses import dataclass + + +@dataclass +class WindowsConsoleFeatures: + """Windows features available.""" + + vt: bool = False + """The console supports VT codes.""" + truecolor: bool = False + """The console supports truecolor.""" + + +try: + import ctypes + from ctypes import LibraryLoader + + if sys.platform == "win32": + windll = LibraryLoader(ctypes.WinDLL) + else: + windll = None + raise ImportError("Not windows") + + from pip._vendor.rich._win32_console import ( + ENABLE_VIRTUAL_TERMINAL_PROCESSING, + GetConsoleMode, + GetStdHandle, + LegacyWindowsError, + ) + +except (AttributeError, ImportError, ValueError): + # Fallback if we can't load the Windows DLL + def get_windows_console_features() -> WindowsConsoleFeatures: + features = WindowsConsoleFeatures() + return features + +else: + + def get_windows_console_features() -> WindowsConsoleFeatures: + """Get windows console features. + + Returns: + WindowsConsoleFeatures: An instance of WindowsConsoleFeatures. + """ + handle = GetStdHandle() + try: + console_mode = GetConsoleMode(handle) + success = True + except LegacyWindowsError: + console_mode = 0 + success = False + vt = bool(success and console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) + truecolor = False + if vt: + win_version = sys.getwindowsversion() + truecolor = win_version.major > 10 or ( + win_version.major == 10 and win_version.build >= 15063 + ) + features = WindowsConsoleFeatures(vt=vt, truecolor=truecolor) + return features + + +if __name__ == "__main__": + import platform + + features = get_windows_console_features() + from pip._vendor.rich import print + + print(f'platform="{platform.system()}"') + print(repr(features)) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py b/venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py new file mode 100644 index 0000000..5ece056 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py @@ -0,0 +1,56 @@ +from typing import Iterable, Sequence, Tuple, cast + +from pip._vendor.rich._win32_console import LegacyWindowsTerm, WindowsCoordinates +from pip._vendor.rich.segment import ControlCode, ControlType, Segment + + +def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) -> None: + """Makes appropriate Windows Console API calls based on the segments in the buffer. + + Args: + buffer (Iterable[Segment]): Iterable of Segments to convert to Win32 API calls. + term (LegacyWindowsTerm): Used to call the Windows Console API. + """ + for text, style, control in buffer: + if not control: + if style: + term.write_styled(text, style) + else: + term.write_text(text) + else: + control_codes: Sequence[ControlCode] = control + for control_code in control_codes: + control_type = control_code[0] + if control_type == ControlType.CURSOR_MOVE_TO: + _, x, y = cast(Tuple[ControlType, int, int], control_code) + term.move_cursor_to(WindowsCoordinates(row=y - 1, col=x - 1)) + elif control_type == ControlType.CARRIAGE_RETURN: + term.write_text("\r") + elif control_type == ControlType.HOME: + term.move_cursor_to(WindowsCoordinates(0, 0)) + elif control_type == ControlType.CURSOR_UP: + term.move_cursor_up() + elif control_type == ControlType.CURSOR_DOWN: + term.move_cursor_down() + elif control_type == ControlType.CURSOR_FORWARD: + term.move_cursor_forward() + elif control_type == ControlType.CURSOR_BACKWARD: + term.move_cursor_backward() + elif control_type == ControlType.CURSOR_MOVE_TO_COLUMN: + _, column = cast(Tuple[ControlType, int], control_code) + term.move_cursor_to_column(column - 1) + elif control_type == ControlType.HIDE_CURSOR: + term.hide_cursor() + elif control_type == ControlType.SHOW_CURSOR: + term.show_cursor() + elif control_type == ControlType.ERASE_IN_LINE: + _, mode = cast(Tuple[ControlType, int], control_code) + if mode == 0: + term.erase_end_of_line() + elif mode == 1: + term.erase_start_of_line() + elif mode == 2: + term.erase_line() + elif control_type == ControlType.SET_WINDOW_TITLE: + _, title = cast(Tuple[ControlType, str], control_code) + term.set_title(title) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/_wrap.py b/venv/Lib/site-packages/pip/_vendor/rich/_wrap.py new file mode 100644 index 0000000..2e94ff6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/_wrap.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import re +from typing import Iterable + +from ._loop import loop_last +from .cells import cell_len, chop_cells + +re_word = re.compile(r"\s*\S+\s*") + + +def words(text: str) -> Iterable[tuple[int, int, str]]: + """Yields each word from the text as a tuple + containing (start_index, end_index, word). A "word" in this context may + include the actual word and any whitespace to the right. + """ + position = 0 + word_match = re_word.match(text, position) + while word_match is not None: + start, end = word_match.span() + word = word_match.group(0) + yield start, end, word + word_match = re_word.match(text, end) + + +def divide_line(text: str, width: int, fold: bool = True) -> list[int]: + """Given a string of text, and a width (measured in cells), return a list + of cell offsets which the string should be split at in order for it to fit + within the given width. + + Args: + text: The text to examine. + width: The available cell width. + fold: If True, words longer than `width` will be folded onto a new line. + + Returns: + A list of indices to break the line at. + """ + break_positions: list[int] = [] # offsets to insert the breaks at + append = break_positions.append + cell_offset = 0 + _cell_len = cell_len + + for start, _end, word in words(text): + word_length = _cell_len(word.rstrip()) + remaining_space = width - cell_offset + word_fits_remaining_space = remaining_space >= word_length + + if word_fits_remaining_space: + # Simplest case - the word fits within the remaining width for this line. + cell_offset += _cell_len(word) + else: + # Not enough space remaining for this word on the current line. + if word_length > width: + # The word doesn't fit on any line, so we can't simply + # place it on the next line... + if fold: + # Fold the word across multiple lines. + folded_word = chop_cells(word, width=width) + for last, line in loop_last(folded_word): + if start: + append(start) + if last: + cell_offset = _cell_len(line) + else: + start += len(line) + else: + # Folding isn't allowed, so crop the word. + if start: + append(start) + cell_offset = _cell_len(word) + elif cell_offset and start: + # The word doesn't fit within the remaining space on the current + # line, but it *can* fit on to the next (empty) line. + append(start) + cell_offset = _cell_len(word) + + return break_positions + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + + console = Console(width=10) + console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345") + print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10)) + + console = Console(width=20) + console.rule() + console.print("TextualはPythonの高速アプリケーション開発フレームワークです") + + console.rule() + console.print("アプリケーションは1670万色を使用でき") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/abc.py b/venv/Lib/site-packages/pip/_vendor/rich/abc.py new file mode 100644 index 0000000..e6e498e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/abc.py @@ -0,0 +1,33 @@ +from abc import ABC + + +class RichRenderable(ABC): + """An abstract base class for Rich renderables. + + Note that there is no need to extend this class, the intended use is to check if an + object supports the Rich renderable protocol. For example:: + + if isinstance(my_object, RichRenderable): + console.print(my_object) + + """ + + @classmethod + def __subclasshook__(cls, other: type) -> bool: + """Check if this class supports the rich render protocol.""" + return hasattr(other, "__rich_console__") or hasattr(other, "__rich__") + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.text import Text + + t = Text() + print(isinstance(Text, RichRenderable)) + print(isinstance(t, RichRenderable)) + + class Foo: + pass + + f = Foo() + print(isinstance(f, RichRenderable)) + print(isinstance("", RichRenderable)) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/align.py b/venv/Lib/site-packages/pip/_vendor/rich/align.py new file mode 100644 index 0000000..f7b734f --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/align.py @@ -0,0 +1,311 @@ +import sys +from itertools import chain +from typing import TYPE_CHECKING, Iterable, Optional + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + +from .constrain import Constrain +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import StyleType + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType, RenderResult + +AlignMethod = Literal["left", "center", "right"] +VerticalAlignMethod = Literal["top", "middle", "bottom"] + + +class Align(JupyterMixin): + """Align a renderable by adding spaces if necessary. + + Args: + renderable (RenderableType): A console renderable. + align (AlignMethod): One of "left", "center", or "right"" + style (StyleType, optional): An optional style to apply to the background. + vertical (Optional[VerticalAlignMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None. + pad (bool, optional): Pad the right with spaces. Defaults to True. + width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None. + height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None. + + Raises: + ValueError: if ``align`` is not one of the expected values. + """ + + def __init__( + self, + renderable: "RenderableType", + align: AlignMethod = "left", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> None: + if align not in ("left", "center", "right"): + raise ValueError( + f'invalid value for align, expected "left", "center", or "right" (not {align!r})' + ) + if vertical is not None and vertical not in ("top", "middle", "bottom"): + raise ValueError( + f'invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r})' + ) + self.renderable = renderable + self.align = align + self.style = style + self.vertical = vertical + self.pad = pad + self.width = width + self.height = height + + def __repr__(self) -> str: + return f"Align({self.renderable!r}, {self.align!r})" + + @classmethod + def left( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the left.""" + return cls( + renderable, + "left", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + @classmethod + def center( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the center.""" + return cls( + renderable, + "center", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + @classmethod + def right( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the right.""" + return cls( + renderable, + "right", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + align = self.align + width = console.measure(self.renderable, options=options).maximum + rendered = console.render( + Constrain( + self.renderable, width if self.width is None else min(width, self.width) + ), + options.update(height=None), + ) + lines = list(Segment.split_lines(rendered)) + width, height = Segment.get_shape(lines) + lines = Segment.set_shape(lines, width, height) + new_line = Segment.line() + excess_space = options.max_width - width + style = console.get_style(self.style) if self.style is not None else None + + def generate_segments() -> Iterable[Segment]: + if excess_space <= 0: + # Exact fit + for line in lines: + yield from line + yield new_line + + elif align == "left": + # Pad on the right + pad = Segment(" " * excess_space, style) if self.pad else None + for line in lines: + yield from line + if pad: + yield pad + yield new_line + + elif align == "center": + # Pad left and right + left = excess_space // 2 + pad = Segment(" " * left, style) + pad_right = ( + Segment(" " * (excess_space - left), style) if self.pad else None + ) + for line in lines: + if left: + yield pad + yield from line + if pad_right: + yield pad_right + yield new_line + + elif align == "right": + # Padding on left + pad = Segment(" " * excess_space, style) + for line in lines: + yield pad + yield from line + yield new_line + + blank_line = ( + Segment(f"{' ' * (self.width or options.max_width)}\n", style) + if self.pad + else Segment("\n") + ) + + def blank_lines(count: int) -> Iterable[Segment]: + if count > 0: + for _ in range(count): + yield blank_line + + vertical_height = self.height or options.height + iter_segments: Iterable[Segment] + if self.vertical and vertical_height is not None: + if self.vertical == "top": + bottom_space = vertical_height - height + iter_segments = chain(generate_segments(), blank_lines(bottom_space)) + elif self.vertical == "middle": + top_space = (vertical_height - height) // 2 + bottom_space = vertical_height - top_space - height + iter_segments = chain( + blank_lines(top_space), + generate_segments(), + blank_lines(bottom_space), + ) + else: # self.vertical == "bottom": + top_space = vertical_height - height + iter_segments = chain(blank_lines(top_space), generate_segments()) + else: + iter_segments = generate_segments() + if self.style: + style = console.get_style(self.style) + iter_segments = Segment.apply_style(iter_segments, style) + yield from iter_segments + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + measurement = Measurement.get(console, options, self.renderable) + return measurement + + +class VerticalCenter(JupyterMixin): + """Vertically aligns a renderable. + + Warn: + This class is deprecated and may be removed in a future version. Use Align class with + `vertical="middle"`. + + Args: + renderable (RenderableType): A renderable object. + """ + + def __init__( + self, + renderable: "RenderableType", + style: Optional[StyleType] = None, + ) -> None: + self.renderable = renderable + self.style = style + + def __repr__(self) -> str: + return f"VerticalCenter({self.renderable!r})" + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + style = console.get_style(self.style) if self.style is not None else None + lines = console.render_lines( + self.renderable, options.update(height=None), pad=False + ) + width, _height = Segment.get_shape(lines) + new_line = Segment.line() + height = options.height or options.size.height + top_space = (height - len(lines)) // 2 + bottom_space = height - top_space - len(lines) + blank_line = Segment(f"{' ' * width}", style) + + def blank_lines(count: int) -> Iterable[Segment]: + for _ in range(count): + yield blank_line + yield new_line + + if top_space > 0: + yield from blank_lines(top_space) + for line in lines: + yield from line + yield new_line + if bottom_space > 0: + yield from blank_lines(bottom_space) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + measurement = Measurement.get(console, options, self.renderable) + return measurement + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console, Group + from pip._vendor.rich.highlighter import ReprHighlighter + from pip._vendor.rich.panel import Panel + + highlighter = ReprHighlighter() + console = Console() + + panel = Panel( + Group( + Align.left(highlighter("align='left'")), + Align.center(highlighter("align='center'")), + Align.right(highlighter("align='right'")), + ), + width=60, + style="on dark_blue", + title="Align", + ) + + console.print( + Align.center(panel, vertical="middle", style="on red", height=console.height) + ) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/ansi.py b/venv/Lib/site-packages/pip/_vendor/rich/ansi.py new file mode 100644 index 0000000..66365e6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/ansi.py @@ -0,0 +1,240 @@ +import re +import sys +from contextlib import suppress +from typing import Iterable, NamedTuple, Optional + +from .color import Color +from .style import Style +from .text import Text + +re_ansi = re.compile( + r""" +(?:\x1b\](.*?)\x1b\\)| +(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~])) +""", + re.VERBOSE, +) + + +class _AnsiToken(NamedTuple): + """Result of ansi tokenized string.""" + + plain: str = "" + sgr: Optional[str] = "" + osc: Optional[str] = "" + + +def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]: + """Tokenize a string in to plain text and ANSI codes. + + Args: + ansi_text (str): A String containing ANSI codes. + + Yields: + AnsiToken: A named tuple of (plain, sgr, osc) + """ + + position = 0 + sgr: Optional[str] + osc: Optional[str] + for match in re_ansi.finditer(ansi_text): + start, end = match.span(0) + osc, sgr = match.groups() + if start > position: + yield _AnsiToken(ansi_text[position:start]) + if sgr: + if sgr == "(": + position = end + 1 + continue + if sgr.endswith("m"): + yield _AnsiToken("", sgr[1:-1], osc) + else: + yield _AnsiToken("", sgr, osc) + position = end + if position < len(ansi_text): + yield _AnsiToken(ansi_text[position:]) + + +SGR_STYLE_MAP = { + 1: "bold", + 2: "dim", + 3: "italic", + 4: "underline", + 5: "blink", + 6: "blink2", + 7: "reverse", + 8: "conceal", + 9: "strike", + 21: "underline2", + 22: "not dim not bold", + 23: "not italic", + 24: "not underline", + 25: "not blink", + 26: "not blink2", + 27: "not reverse", + 28: "not conceal", + 29: "not strike", + 30: "color(0)", + 31: "color(1)", + 32: "color(2)", + 33: "color(3)", + 34: "color(4)", + 35: "color(5)", + 36: "color(6)", + 37: "color(7)", + 39: "default", + 40: "on color(0)", + 41: "on color(1)", + 42: "on color(2)", + 43: "on color(3)", + 44: "on color(4)", + 45: "on color(5)", + 46: "on color(6)", + 47: "on color(7)", + 49: "on default", + 51: "frame", + 52: "encircle", + 53: "overline", + 54: "not frame not encircle", + 55: "not overline", + 90: "color(8)", + 91: "color(9)", + 92: "color(10)", + 93: "color(11)", + 94: "color(12)", + 95: "color(13)", + 96: "color(14)", + 97: "color(15)", + 100: "on color(8)", + 101: "on color(9)", + 102: "on color(10)", + 103: "on color(11)", + 104: "on color(12)", + 105: "on color(13)", + 106: "on color(14)", + 107: "on color(15)", +} + + +class AnsiDecoder: + """Translate ANSI code in to styled Text.""" + + def __init__(self) -> None: + self.style = Style.null() + + def decode(self, terminal_text: str) -> Iterable[Text]: + """Decode ANSI codes in an iterable of lines. + + Args: + lines (Iterable[str]): An iterable of lines of terminal output. + + Yields: + Text: Marked up Text. + """ + for line in terminal_text.splitlines(): + yield self.decode_line(line) + + def decode_line(self, line: str) -> Text: + """Decode a line containing ansi codes. + + Args: + line (str): A line of terminal output. + + Returns: + Text: A Text instance marked up according to ansi codes. + """ + from_ansi = Color.from_ansi + from_rgb = Color.from_rgb + _Style = Style + text = Text() + append = text.append + line = line.rsplit("\r", 1)[-1] + for plain_text, sgr, osc in _ansi_tokenize(line): + if plain_text: + append(plain_text, self.style or None) + elif osc is not None: + if osc.startswith("8;"): + _params, semicolon, link = osc[2:].partition(";") + if semicolon: + self.style = self.style.update_link(link or None) + elif sgr is not None: + # Translate in to semi-colon separated codes + # Ignore invalid codes, because we want to be lenient + codes = [ + min(255, int(_code) if _code else 0) + for _code in sgr.split(";") + if _code.isdigit() or _code == "" + ] + iter_codes = iter(codes) + for code in iter_codes: + if code == 0: + # reset + self.style = _Style.null() + elif code in SGR_STYLE_MAP: + # styles + self.style += _Style.parse(SGR_STYLE_MAP[code]) + elif code == 38: + #  Foreground + with suppress(StopIteration): + color_type = next(iter_codes) + if color_type == 5: + self.style += _Style.from_color( + from_ansi(next(iter_codes)) + ) + elif color_type == 2: + self.style += _Style.from_color( + from_rgb( + next(iter_codes), + next(iter_codes), + next(iter_codes), + ) + ) + elif code == 48: + # Background + with suppress(StopIteration): + color_type = next(iter_codes) + if color_type == 5: + self.style += _Style.from_color( + None, from_ansi(next(iter_codes)) + ) + elif color_type == 2: + self.style += _Style.from_color( + None, + from_rgb( + next(iter_codes), + next(iter_codes), + next(iter_codes), + ), + ) + + return text + + +if sys.platform != "win32" and __name__ == "__main__": # pragma: no cover + import io + import os + import pty + import sys + + decoder = AnsiDecoder() + + stdout = io.BytesIO() + + def read(fd: int) -> bytes: + data = os.read(fd, 1024) + stdout.write(data) + return data + + pty.spawn(sys.argv[1:], read) + + from .console import Console + + console = Console(record=True) + + stdout_result = stdout.getvalue().decode("utf-8") + print(stdout_result) + + for line in decoder.decode(stdout_result): + console.print(line) + + console.save_html("stdout.html") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/bar.py b/venv/Lib/site-packages/pip/_vendor/rich/bar.py new file mode 100644 index 0000000..022284b --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/bar.py @@ -0,0 +1,93 @@ +from typing import Optional, Union + +from .color import Color +from .console import Console, ConsoleOptions, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import Style + +# There are left-aligned characters for 1/8 to 7/8, but +# the right-aligned characters exist only for 1/8 and 4/8. +BEGIN_BLOCK_ELEMENTS = ["█", "█", "█", "▐", "▐", "▐", "▕", "▕"] +END_BLOCK_ELEMENTS = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"] +FULL_BLOCK = "█" + + +class Bar(JupyterMixin): + """Renders a solid block bar. + + Args: + size (float): Value for the end of the bar. + begin (float): Begin point (between 0 and size, inclusive). + end (float): End point (between 0 and size, inclusive). + width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None. + color (Union[Color, str], optional): Color of the bar. Defaults to "default". + bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default". + """ + + def __init__( + self, + size: float, + begin: float, + end: float, + *, + width: Optional[int] = None, + color: Union[Color, str] = "default", + bgcolor: Union[Color, str] = "default", + ): + self.size = size + self.begin = max(begin, 0) + self.end = min(end, size) + self.width = width + self.style = Style(color=color, bgcolor=bgcolor) + + def __repr__(self) -> str: + return f"Bar({self.size}, {self.begin}, {self.end})" + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + width = min( + self.width if self.width is not None else options.max_width, + options.max_width, + ) + + if self.begin >= self.end: + yield Segment(" " * width, self.style) + yield Segment.line() + return + + prefix_complete_eights = int(width * 8 * self.begin / self.size) + prefix_bar_count = prefix_complete_eights // 8 + prefix_eights_count = prefix_complete_eights % 8 + + body_complete_eights = int(width * 8 * self.end / self.size) + body_bar_count = body_complete_eights // 8 + body_eights_count = body_complete_eights % 8 + + # When start and end fall into the same cell, we ideally should render + # a symbol that's "center-aligned", but there is no good symbol in Unicode. + # In this case, we fall back to right-aligned block symbol for simplicity. + + prefix = " " * prefix_bar_count + if prefix_eights_count: + prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count] + + body = FULL_BLOCK * body_bar_count + if body_eights_count: + body += END_BLOCK_ELEMENTS[body_eights_count] + + suffix = " " * (width - len(body)) + + yield Segment(prefix + body[len(prefix) :] + suffix, self.style) + yield Segment.line() + + def __rich_measure__( + self, console: Console, options: ConsoleOptions + ) -> Measurement: + return ( + Measurement(self.width, self.width) + if self.width is not None + else Measurement(4, options.max_width) + ) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/box.py b/venv/Lib/site-packages/pip/_vendor/rich/box.py new file mode 100644 index 0000000..0511a9e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/box.py @@ -0,0 +1,480 @@ +import sys +from typing import TYPE_CHECKING, Iterable, List + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + + +from ._loop import loop_last + +if TYPE_CHECKING: + from pip._vendor.rich.console import ConsoleOptions + + +class Box: + """Defines characters to render boxes. + + ┌─┬┐ top + │ ││ head + ├─┼┤ head_row + │ ││ mid + ├─┼┤ row + ├─┼┤ foot_row + │ ││ foot + └─┴┘ bottom + + Args: + box (str): Characters making up box. + ascii (bool, optional): True if this box uses ascii characters only. Default is False. + """ + + def __init__(self, box: str, *, ascii: bool = False) -> None: + self._box = box + self.ascii = ascii + line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines() + # top + self.top_left, self.top, self.top_divider, self.top_right = iter(line1) + # head + self.head_left, _, self.head_vertical, self.head_right = iter(line2) + # head_row + ( + self.head_row_left, + self.head_row_horizontal, + self.head_row_cross, + self.head_row_right, + ) = iter(line3) + + # mid + self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4) + # row + self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5) + # foot_row + ( + self.foot_row_left, + self.foot_row_horizontal, + self.foot_row_cross, + self.foot_row_right, + ) = iter(line6) + # foot + self.foot_left, _, self.foot_vertical, self.foot_right = iter(line7) + # bottom + self.bottom_left, self.bottom, self.bottom_divider, self.bottom_right = iter( + line8 + ) + + def __repr__(self) -> str: + return "Box(...)" + + def __str__(self) -> str: + return self._box + + def substitute(self, options: "ConsoleOptions", safe: bool = True) -> "Box": + """Substitute this box for another if it won't render due to platform issues. + + Args: + options (ConsoleOptions): Console options used in rendering. + safe (bool, optional): Substitute this for another Box if there are known problems + displaying on the platform (currently only relevant on Windows). Default is True. + + Returns: + Box: A different Box or the same Box. + """ + box = self + if options.legacy_windows and safe: + box = LEGACY_WINDOWS_SUBSTITUTIONS.get(box, box) + if options.ascii_only and not box.ascii: + box = ASCII + return box + + def get_plain_headed_box(self) -> "Box": + """If this box uses special characters for the borders of the header, then + return the equivalent box that does not. + + Returns: + Box: The most similar Box that doesn't use header-specific box characters. + If the current Box already satisfies this criterion, then it's returned. + """ + return PLAIN_HEADED_SUBSTITUTIONS.get(self, self) + + def get_top(self, widths: Iterable[int]) -> str: + """Get the top of a simple box. + + Args: + widths (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + + parts: List[str] = [] + append = parts.append + append(self.top_left) + for last, width in loop_last(widths): + append(self.top * width) + if not last: + append(self.top_divider) + append(self.top_right) + return "".join(parts) + + def get_row( + self, + widths: Iterable[int], + level: Literal["head", "row", "foot", "mid"] = "row", + edge: bool = True, + ) -> str: + """Get the top of a simple box. + + Args: + width (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + if level == "head": + left = self.head_row_left + horizontal = self.head_row_horizontal + cross = self.head_row_cross + right = self.head_row_right + elif level == "row": + left = self.row_left + horizontal = self.row_horizontal + cross = self.row_cross + right = self.row_right + elif level == "mid": + left = self.mid_left + horizontal = " " + cross = self.mid_vertical + right = self.mid_right + elif level == "foot": + left = self.foot_row_left + horizontal = self.foot_row_horizontal + cross = self.foot_row_cross + right = self.foot_row_right + else: + raise ValueError("level must be 'head', 'row' or 'foot'") + + parts: List[str] = [] + append = parts.append + if edge: + append(left) + for last, width in loop_last(widths): + append(horizontal * width) + if not last: + append(cross) + if edge: + append(right) + return "".join(parts) + + def get_bottom(self, widths: Iterable[int]) -> str: + """Get the bottom of a simple box. + + Args: + widths (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + + parts: List[str] = [] + append = parts.append + append(self.bottom_left) + for last, width in loop_last(widths): + append(self.bottom * width) + if not last: + append(self.bottom_divider) + append(self.bottom_right) + return "".join(parts) + + +# fmt: off +ASCII: Box = Box( + "+--+\n" + "| ||\n" + "|-+|\n" + "| ||\n" + "|-+|\n" + "|-+|\n" + "| ||\n" + "+--+\n", + ascii=True, +) + +ASCII2: Box = Box( + "+-++\n" + "| ||\n" + "+-++\n" + "| ||\n" + "+-++\n" + "+-++\n" + "| ||\n" + "+-++\n", + ascii=True, +) + +ASCII_DOUBLE_HEAD: Box = Box( + "+-++\n" + "| ||\n" + "+=++\n" + "| ||\n" + "+-++\n" + "+-++\n" + "| ||\n" + "+-++\n", + ascii=True, +) + +SQUARE: Box = Box( + "┌─┬┐\n" + "│ ││\n" + "├─┼┤\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +SQUARE_DOUBLE_HEAD: Box = Box( + "┌─┬┐\n" + "│ ││\n" + "╞═╪╡\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +MINIMAL: Box = Box( + " ╷ \n" + " │ \n" + "╶─┼╴\n" + " │ \n" + "╶─┼╴\n" + "╶─┼╴\n" + " │ \n" + " ╵ \n" +) + + +MINIMAL_HEAVY_HEAD: Box = Box( + " ╷ \n" + " │ \n" + "╺━┿╸\n" + " │ \n" + "╶─┼╴\n" + "╶─┼╴\n" + " │ \n" + " ╵ \n" +) + +MINIMAL_DOUBLE_HEAD: Box = Box( + " ╷ \n" + " │ \n" + " ═╪ \n" + " │ \n" + " ─┼ \n" + " ─┼ \n" + " │ \n" + " ╵ \n" +) + + +SIMPLE: Box = Box( + " \n" + " \n" + " ── \n" + " \n" + " \n" + " ── \n" + " \n" + " \n" +) + +SIMPLE_HEAD: Box = Box( + " \n" + " \n" + " ── \n" + " \n" + " \n" + " \n" + " \n" + " \n" +) + + +SIMPLE_HEAVY: Box = Box( + " \n" + " \n" + " ━━ \n" + " \n" + " \n" + " ━━ \n" + " \n" + " \n" +) + + +HORIZONTALS: Box = Box( + " ── \n" + " \n" + " ── \n" + " \n" + " ── \n" + " ── \n" + " \n" + " ── \n" +) + +ROUNDED: Box = Box( + "╭─┬╮\n" + "│ ││\n" + "├─┼┤\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "╰─┴╯\n" +) + +HEAVY: Box = Box( + "┏━┳┓\n" + "┃ ┃┃\n" + "┣━╋┫\n" + "┃ ┃┃\n" + "┣━╋┫\n" + "┣━╋┫\n" + "┃ ┃┃\n" + "┗━┻┛\n" +) + +HEAVY_EDGE: Box = Box( + "┏━┯┓\n" + "┃ │┃\n" + "┠─┼┨\n" + "┃ │┃\n" + "┠─┼┨\n" + "┠─┼┨\n" + "┃ │┃\n" + "┗━┷┛\n" +) + +HEAVY_HEAD: Box = Box( + "┏━┳┓\n" + "┃ ┃┃\n" + "┡━╇┩\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +DOUBLE: Box = Box( + "╔═╦╗\n" + "║ ║║\n" + "╠═╬╣\n" + "║ ║║\n" + "╠═╬╣\n" + "╠═╬╣\n" + "║ ║║\n" + "╚═╩╝\n" +) + +DOUBLE_EDGE: Box = Box( + "╔═╤╗\n" + "║ │║\n" + "╟─┼╢\n" + "║ │║\n" + "╟─┼╢\n" + "╟─┼╢\n" + "║ │║\n" + "╚═╧╝\n" +) + +MARKDOWN: Box = Box( + " \n" + "| ||\n" + "|-||\n" + "| ||\n" + "|-||\n" + "|-||\n" + "| ||\n" + " \n", + ascii=True, +) +# fmt: on + +# Map Boxes that don't render with raster fonts on to equivalent that do +LEGACY_WINDOWS_SUBSTITUTIONS = { + ROUNDED: SQUARE, + MINIMAL_HEAVY_HEAD: MINIMAL, + SIMPLE_HEAVY: SIMPLE, + HEAVY: SQUARE, + HEAVY_EDGE: SQUARE, + HEAVY_HEAD: SQUARE, +} + +# Map headed boxes to their headerless equivalents +PLAIN_HEADED_SUBSTITUTIONS = { + HEAVY_HEAD: SQUARE, + SQUARE_DOUBLE_HEAD: SQUARE, + MINIMAL_DOUBLE_HEAD: MINIMAL, + MINIMAL_HEAVY_HEAD: MINIMAL, + ASCII_DOUBLE_HEAD: ASCII2, +} + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.columns import Columns + from pip._vendor.rich.panel import Panel + + from . import box as box + from .console import Console + from .table import Table + from .text import Text + + console = Console(record=True) + + BOXES = [ + "ASCII", + "ASCII2", + "ASCII_DOUBLE_HEAD", + "SQUARE", + "SQUARE_DOUBLE_HEAD", + "MINIMAL", + "MINIMAL_HEAVY_HEAD", + "MINIMAL_DOUBLE_HEAD", + "SIMPLE", + "SIMPLE_HEAD", + "SIMPLE_HEAVY", + "HORIZONTALS", + "ROUNDED", + "HEAVY", + "HEAVY_EDGE", + "HEAVY_HEAD", + "DOUBLE", + "DOUBLE_EDGE", + "MARKDOWN", + ] + + console.print(Panel("[bold green]Box Constants", style="green"), justify="center") + console.print() + + columns = Columns(expand=True, padding=2) + for box_name in sorted(BOXES): + table = Table( + show_footer=True, style="dim", border_style="not dim", expand=True + ) + table.add_column("Header 1", "Footer 1") + table.add_column("Header 2", "Footer 2") + table.add_row("Cell", "Cell") + table.add_row("Cell", "Cell") + table.box = getattr(box, box_name) + table.title = Text(f"box.{box_name}", style="magenta") + columns.add_renderable(table) + console.print(columns) + + # console.save_svg("box.svg") diff --git a/venv/Lib/site-packages/pip/_vendor/rich/cells.py b/venv/Lib/site-packages/pip/_vendor/rich/cells.py new file mode 100644 index 0000000..f85f928 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/cells.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +import re +from functools import lru_cache +from typing import Callable + +from ._cell_widths import CELL_WIDTHS + +# Regex to match sequence of the most common character ranges +_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match + + +@lru_cache(4096) +def cached_cell_len(text: str) -> int: + """Get the number of cells required to display text. + + This method always caches, which may use up a lot of memory. It is recommended to use + `cell_len` over this method. + + Args: + text (str): Text to display. + + Returns: + int: Get the number of cells required to display text. + """ + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size + + +def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int: + """Get the number of cells required to display text. + + Args: + text (str): Text to display. + + Returns: + int: Get the number of cells required to display text. + """ + if len(text) < 512: + return _cell_len(text) + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size + + +@lru_cache(maxsize=4096) +def get_character_cell_size(character: str) -> int: + """Get the cell size of a character. + + Args: + character (str): A single character. + + Returns: + int: Number of cells (0, 1 or 2) occupied by that character. + """ + return _get_codepoint_cell_size(ord(character)) + + +@lru_cache(maxsize=4096) +def _get_codepoint_cell_size(codepoint: int) -> int: + """Get the cell size of a character. + + Args: + codepoint (int): Codepoint of a character. + + Returns: + int: Number of cells (0, 1 or 2) occupied by that character. + """ + + _table = CELL_WIDTHS + lower_bound = 0 + upper_bound = len(_table) - 1 + index = (lower_bound + upper_bound) // 2 + while True: + start, end, width = _table[index] + if codepoint < start: + upper_bound = index - 1 + elif codepoint > end: + lower_bound = index + 1 + else: + return 0 if width == -1 else width + if upper_bound < lower_bound: + break + index = (lower_bound + upper_bound) // 2 + return 1 + + +def set_cell_size(text: str, total: int) -> str: + """Set the length of a string to fit within given number of cells.""" + + if _is_single_cell_widths(text): + size = len(text) + if size < total: + return text + " " * (total - size) + return text[:total] + + if total <= 0: + return "" + cell_size = cell_len(text) + if cell_size == total: + return text + if cell_size < total: + return text + " " * (total - cell_size) + + start = 0 + end = len(text) + + # Binary search until we find the right size + while True: + pos = (start + end) // 2 + before = text[: pos + 1] + before_len = cell_len(before) + if before_len == total + 1 and cell_len(before[-1]) == 2: + return before[:-1] + " " + if before_len == total: + return before + if before_len > total: + end = pos + else: + start = pos + + +def chop_cells( + text: str, + width: int, +) -> list[str]: + """Split text into lines such that each line fits within the available (cell) width. + + Args: + text: The text to fold such that it fits in the given width. + width: The width available (number of cells). + + Returns: + A list of strings such that each string in the list has cell width + less than or equal to the available width. + """ + _get_character_cell_size = get_character_cell_size + lines: list[list[str]] = [[]] + + append_new_line = lines.append + append_to_last_line = lines[-1].append + + total_width = 0 + + for character in text: + cell_width = _get_character_cell_size(character) + char_doesnt_fit = total_width + cell_width > width + + if char_doesnt_fit: + append_new_line([character]) + append_to_last_line = lines[-1].append + total_width = cell_width + else: + append_to_last_line(character) + total_width += cell_width + + return ["".join(line) for line in lines] + + +if __name__ == "__main__": # pragma: no cover + print(get_character_cell_size("😽")) + for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8): + print(line) + for n in range(80, 1, -1): + print(set_cell_size("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", n) + "|") + print("x" * n) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/color.py b/venv/Lib/site-packages/pip/_vendor/rich/color.py new file mode 100644 index 0000000..4270a27 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/color.py @@ -0,0 +1,621 @@ +import platform +import re +from colorsys import rgb_to_hls +from enum import IntEnum +from functools import lru_cache +from typing import TYPE_CHECKING, NamedTuple, Optional, Tuple + +from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE +from .color_triplet import ColorTriplet +from .repr import Result, rich_repr +from .terminal_theme import DEFAULT_TERMINAL_THEME + +if TYPE_CHECKING: # pragma: no cover + from .terminal_theme import TerminalTheme + from .text import Text + + +WINDOWS = platform.system() == "Windows" + + +class ColorSystem(IntEnum): + """One of the 3 color system supported by terminals.""" + + STANDARD = 1 + EIGHT_BIT = 2 + TRUECOLOR = 3 + WINDOWS = 4 + + def __repr__(self) -> str: + return f"ColorSystem.{self.name}" + + def __str__(self) -> str: + return repr(self) + + +class ColorType(IntEnum): + """Type of color stored in Color class.""" + + DEFAULT = 0 + STANDARD = 1 + EIGHT_BIT = 2 + TRUECOLOR = 3 + WINDOWS = 4 + + def __repr__(self) -> str: + return f"ColorType.{self.name}" + + +ANSI_COLOR_NAMES = { + "black": 0, + "red": 1, + "green": 2, + "yellow": 3, + "blue": 4, + "magenta": 5, + "cyan": 6, + "white": 7, + "bright_black": 8, + "bright_red": 9, + "bright_green": 10, + "bright_yellow": 11, + "bright_blue": 12, + "bright_magenta": 13, + "bright_cyan": 14, + "bright_white": 15, + "grey0": 16, + "gray0": 16, + "navy_blue": 17, + "dark_blue": 18, + "blue3": 20, + "blue1": 21, + "dark_green": 22, + "deep_sky_blue4": 25, + "dodger_blue3": 26, + "dodger_blue2": 27, + "green4": 28, + "spring_green4": 29, + "turquoise4": 30, + "deep_sky_blue3": 32, + "dodger_blue1": 33, + "green3": 40, + "spring_green3": 41, + "dark_cyan": 36, + "light_sea_green": 37, + "deep_sky_blue2": 38, + "deep_sky_blue1": 39, + "spring_green2": 47, + "cyan3": 43, + "dark_turquoise": 44, + "turquoise2": 45, + "green1": 46, + "spring_green1": 48, + "medium_spring_green": 49, + "cyan2": 50, + "cyan1": 51, + "dark_red": 88, + "deep_pink4": 125, + "purple4": 55, + "purple3": 56, + "blue_violet": 57, + "orange4": 94, + "grey37": 59, + "gray37": 59, + "medium_purple4": 60, + "slate_blue3": 62, + "royal_blue1": 63, + "chartreuse4": 64, + "dark_sea_green4": 71, + "pale_turquoise4": 66, + "steel_blue": 67, + "steel_blue3": 68, + "cornflower_blue": 69, + "chartreuse3": 76, + "cadet_blue": 73, + "sky_blue3": 74, + "steel_blue1": 81, + "pale_green3": 114, + "sea_green3": 78, + "aquamarine3": 79, + "medium_turquoise": 80, + "chartreuse2": 112, + "sea_green2": 83, + "sea_green1": 85, + "aquamarine1": 122, + "dark_slate_gray2": 87, + "dark_magenta": 91, + "dark_violet": 128, + "purple": 129, + "light_pink4": 95, + "plum4": 96, + "medium_purple3": 98, + "slate_blue1": 99, + "yellow4": 106, + "wheat4": 101, + "grey53": 102, + "gray53": 102, + "light_slate_grey": 103, + "light_slate_gray": 103, + "medium_purple": 104, + "light_slate_blue": 105, + "dark_olive_green3": 149, + "dark_sea_green": 108, + "light_sky_blue3": 110, + "sky_blue2": 111, + "dark_sea_green3": 150, + "dark_slate_gray3": 116, + "sky_blue1": 117, + "chartreuse1": 118, + "light_green": 120, + "pale_green1": 156, + "dark_slate_gray1": 123, + "red3": 160, + "medium_violet_red": 126, + "magenta3": 164, + "dark_orange3": 166, + "indian_red": 167, + "hot_pink3": 168, + "medium_orchid3": 133, + "medium_orchid": 134, + "medium_purple2": 140, + "dark_goldenrod": 136, + "light_salmon3": 173, + "rosy_brown": 138, + "grey63": 139, + "gray63": 139, + "medium_purple1": 141, + "gold3": 178, + "dark_khaki": 143, + "navajo_white3": 144, + "grey69": 145, + "gray69": 145, + "light_steel_blue3": 146, + "light_steel_blue": 147, + "yellow3": 184, + "dark_sea_green2": 157, + "light_cyan3": 152, + "light_sky_blue1": 153, + "green_yellow": 154, + "dark_olive_green2": 155, + "dark_sea_green1": 193, + "pale_turquoise1": 159, + "deep_pink3": 162, + "magenta2": 200, + "hot_pink2": 169, + "orchid": 170, + "medium_orchid1": 207, + "orange3": 172, + "light_pink3": 174, + "pink3": 175, + "plum3": 176, + "violet": 177, + "light_goldenrod3": 179, + "tan": 180, + "misty_rose3": 181, + "thistle3": 182, + "plum2": 183, + "khaki3": 185, + "light_goldenrod2": 222, + "light_yellow3": 187, + "grey84": 188, + "gray84": 188, + "light_steel_blue1": 189, + "yellow2": 190, + "dark_olive_green1": 192, + "honeydew2": 194, + "light_cyan1": 195, + "red1": 196, + "deep_pink2": 197, + "deep_pink1": 199, + "magenta1": 201, + "orange_red1": 202, + "indian_red1": 204, + "hot_pink": 206, + "dark_orange": 208, + "salmon1": 209, + "light_coral": 210, + "pale_violet_red1": 211, + "orchid2": 212, + "orchid1": 213, + "orange1": 214, + "sandy_brown": 215, + "light_salmon1": 216, + "light_pink1": 217, + "pink1": 218, + "plum1": 219, + "gold1": 220, + "navajo_white1": 223, + "misty_rose1": 224, + "thistle1": 225, + "yellow1": 226, + "light_goldenrod1": 227, + "khaki1": 228, + "wheat1": 229, + "cornsilk1": 230, + "grey100": 231, + "gray100": 231, + "grey3": 232, + "gray3": 232, + "grey7": 233, + "gray7": 233, + "grey11": 234, + "gray11": 234, + "grey15": 235, + "gray15": 235, + "grey19": 236, + "gray19": 236, + "grey23": 237, + "gray23": 237, + "grey27": 238, + "gray27": 238, + "grey30": 239, + "gray30": 239, + "grey35": 240, + "gray35": 240, + "grey39": 241, + "gray39": 241, + "grey42": 242, + "gray42": 242, + "grey46": 243, + "gray46": 243, + "grey50": 244, + "gray50": 244, + "grey54": 245, + "gray54": 245, + "grey58": 246, + "gray58": 246, + "grey62": 247, + "gray62": 247, + "grey66": 248, + "gray66": 248, + "grey70": 249, + "gray70": 249, + "grey74": 250, + "gray74": 250, + "grey78": 251, + "gray78": 251, + "grey82": 252, + "gray82": 252, + "grey85": 253, + "gray85": 253, + "grey89": 254, + "gray89": 254, + "grey93": 255, + "gray93": 255, +} + + +class ColorParseError(Exception): + """The color could not be parsed.""" + + +RE_COLOR = re.compile( + r"""^ +\#([0-9a-f]{6})$| +color\(([0-9]{1,3})\)$| +rgb\(([\d\s,]+)\)$ +""", + re.VERBOSE, +) + + +@rich_repr +class Color(NamedTuple): + """Terminal color definition.""" + + name: str + """The name of the color (typically the input to Color.parse).""" + type: ColorType + """The type of the color.""" + number: Optional[int] = None + """The color number, if a standard color, or None.""" + triplet: Optional[ColorTriplet] = None + """A triplet of color components, if an RGB color.""" + + def __rich__(self) -> "Text": + """Displays the actual color if Rich printed.""" + from .style import Style + from .text import Text + + return Text.assemble( + f"", + ) + + def __rich_repr__(self) -> Result: + yield self.name + yield self.type + yield "number", self.number, None + yield "triplet", self.triplet, None + + @property + def system(self) -> ColorSystem: + """Get the native color system for this color.""" + if self.type == ColorType.DEFAULT: + return ColorSystem.STANDARD + return ColorSystem(int(self.type)) + + @property + def is_system_defined(self) -> bool: + """Check if the color is ultimately defined by the system.""" + return self.system not in (ColorSystem.EIGHT_BIT, ColorSystem.TRUECOLOR) + + @property + def is_default(self) -> bool: + """Check if the color is a default color.""" + return self.type == ColorType.DEFAULT + + def get_truecolor( + self, theme: Optional["TerminalTheme"] = None, foreground: bool = True + ) -> ColorTriplet: + """Get an equivalent color triplet for this color. + + Args: + theme (TerminalTheme, optional): Optional terminal theme, or None to use default. Defaults to None. + foreground (bool, optional): True for a foreground color, or False for background. Defaults to True. + + Returns: + ColorTriplet: A color triplet containing RGB components. + """ + + if theme is None: + theme = DEFAULT_TERMINAL_THEME + if self.type == ColorType.TRUECOLOR: + assert self.triplet is not None + return self.triplet + elif self.type == ColorType.EIGHT_BIT: + assert self.number is not None + return EIGHT_BIT_PALETTE[self.number] + elif self.type == ColorType.STANDARD: + assert self.number is not None + return theme.ansi_colors[self.number] + elif self.type == ColorType.WINDOWS: + assert self.number is not None + return WINDOWS_PALETTE[self.number] + else: # self.type == ColorType.DEFAULT: + assert self.number is None + return theme.foreground_color if foreground else theme.background_color + + @classmethod + def from_ansi(cls, number: int) -> "Color": + """Create a Color number from it's 8-bit ansi number. + + Args: + number (int): A number between 0-255 inclusive. + + Returns: + Color: A new Color instance. + """ + return cls( + name=f"color({number})", + type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), + number=number, + ) + + @classmethod + def from_triplet(cls, triplet: "ColorTriplet") -> "Color": + """Create a truecolor RGB color from a triplet of values. + + Args: + triplet (ColorTriplet): A color triplet containing red, green and blue components. + + Returns: + Color: A new color object. + """ + return cls(name=triplet.hex, type=ColorType.TRUECOLOR, triplet=triplet) + + @classmethod + def from_rgb(cls, red: float, green: float, blue: float) -> "Color": + """Create a truecolor from three color components in the range(0->255). + + Args: + red (float): Red component in range 0-255. + green (float): Green component in range 0-255. + blue (float): Blue component in range 0-255. + + Returns: + Color: A new color object. + """ + return cls.from_triplet(ColorTriplet(int(red), int(green), int(blue))) + + @classmethod + def default(cls) -> "Color": + """Get a Color instance representing the default color. + + Returns: + Color: Default color. + """ + return cls(name="default", type=ColorType.DEFAULT) + + @classmethod + @lru_cache(maxsize=1024) + def parse(cls, color: str) -> "Color": + """Parse a color definition.""" + original_color = color + color = color.lower().strip() + + if color == "default": + return cls(color, type=ColorType.DEFAULT) + + color_number = ANSI_COLOR_NAMES.get(color) + if color_number is not None: + return cls( + color, + type=(ColorType.STANDARD if color_number < 16 else ColorType.EIGHT_BIT), + number=color_number, + ) + + color_match = RE_COLOR.match(color) + if color_match is None: + raise ColorParseError(f"{original_color!r} is not a valid color") + + color_24, color_8, color_rgb = color_match.groups() + if color_24: + triplet = ColorTriplet( + int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16) + ) + return cls(color, ColorType.TRUECOLOR, triplet=triplet) + + elif color_8: + number = int(color_8) + if number > 255: + raise ColorParseError(f"color number must be <= 255 in {color!r}") + return cls( + color, + type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), + number=number, + ) + + else: # color_rgb: + components = color_rgb.split(",") + if len(components) != 3: + raise ColorParseError( + f"expected three components in {original_color!r}" + ) + red, green, blue = components + triplet = ColorTriplet(int(red), int(green), int(blue)) + if not all(component <= 255 for component in triplet): + raise ColorParseError( + f"color components must be <= 255 in {original_color!r}" + ) + return cls(color, ColorType.TRUECOLOR, triplet=triplet) + + @lru_cache(maxsize=1024) + def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]: + """Get the ANSI escape codes for this color.""" + _type = self.type + if _type == ColorType.DEFAULT: + return ("39" if foreground else "49",) + + elif _type == ColorType.WINDOWS: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.STANDARD: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.EIGHT_BIT: + assert self.number is not None + return ("38" if foreground else "48", "5", str(self.number)) + + else: # self.standard == ColorStandard.TRUECOLOR: + assert self.triplet is not None + red, green, blue = self.triplet + return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) + + @lru_cache(maxsize=1024) + def downgrade(self, system: ColorSystem) -> "Color": + """Downgrade a color system to a system with fewer colors.""" + + if self.type in (ColorType.DEFAULT, system): + return self + # Convert to 8-bit color from truecolor color + if system == ColorSystem.EIGHT_BIT and self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + _h, l, s = rgb_to_hls(*self.triplet.normalized) + # If saturation is under 15% assume it is grayscale + if s < 0.15: + gray = round(l * 25.0) + if gray == 0: + color_number = 16 + elif gray == 25: + color_number = 231 + else: + color_number = 231 + gray + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + red, green, blue = self.triplet + six_red = red / 95 if red < 95 else 1 + (red - 95) / 40 + six_green = green / 95 if green < 95 else 1 + (green - 95) / 40 + six_blue = blue / 95 if blue < 95 else 1 + (blue - 95) / 40 + + color_number = ( + 16 + 36 * round(six_red) + 6 * round(six_green) + round(six_blue) + ) + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + # Convert to standard from truecolor or 8-bit + elif system == ColorSystem.STANDARD: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = STANDARD_PALETTE.match(triplet) + return Color(self.name, ColorType.STANDARD, number=color_number) + + elif system == ColorSystem.WINDOWS: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + if self.number < 16: + return Color(self.name, ColorType.WINDOWS, number=self.number) + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = WINDOWS_PALETTE.match(triplet) + return Color(self.name, ColorType.WINDOWS, number=color_number) + + return self + + +def parse_rgb_hex(hex_color: str) -> ColorTriplet: + """Parse six hex characters in to RGB triplet.""" + assert len(hex_color) == 6, "must be 6 characters" + color = ColorTriplet( + int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) + ) + return color + + +def blend_rgb( + color1: ColorTriplet, color2: ColorTriplet, cross_fade: float = 0.5 +) -> ColorTriplet: + """Blend one RGB color in to another.""" + r1, g1, b1 = color1 + r2, g2, b2 = color2 + new_color = ColorTriplet( + int(r1 + (r2 - r1) * cross_fade), + int(g1 + (g2 - g1) * cross_fade), + int(b1 + (b2 - b1) * cross_fade), + ) + return new_color + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + from .table import Table + from .text import Text + + console = Console() + + table = Table(show_footer=False, show_edge=True) + table.add_column("Color", width=10, overflow="ellipsis") + table.add_column("Number", justify="right", style="yellow") + table.add_column("Name", style="green") + table.add_column("Hex", style="blue") + table.add_column("RGB", style="magenta") + + colors = sorted((v, k) for k, v in ANSI_COLOR_NAMES.items()) + for color_number, name in colors: + if "grey" in name: + continue + color_cell = Text(" " * 10, style=f"on {name}") + if color_number < 16: + table.add_row(color_cell, f"{color_number}", Text(f'"{name}"')) + else: + color = EIGHT_BIT_PALETTE[color_number] # type: ignore[has-type] + table.add_row( + color_cell, str(color_number), Text(f'"{name}"'), color.hex, color.rgb + ) + + console.print(table) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py b/venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py new file mode 100644 index 0000000..02cab32 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py @@ -0,0 +1,38 @@ +from typing import NamedTuple, Tuple + + +class ColorTriplet(NamedTuple): + """The red, green, and blue components of a color.""" + + red: int + """Red component in 0 to 255 range.""" + green: int + """Green component in 0 to 255 range.""" + blue: int + """Blue component in 0 to 255 range.""" + + @property + def hex(self) -> str: + """get the color triplet in CSS style.""" + red, green, blue = self + return f"#{red:02x}{green:02x}{blue:02x}" + + @property + def rgb(self) -> str: + """The color in RGB format. + + Returns: + str: An rgb color, e.g. ``"rgb(100,23,255)"``. + """ + red, green, blue = self + return f"rgb({red},{green},{blue})" + + @property + def normalized(self) -> Tuple[float, float, float]: + """Convert components into floats between 0 and 1. + + Returns: + Tuple[float, float, float]: A tuple of three normalized colour components. + """ + red, green, blue = self + return red / 255.0, green / 255.0, blue / 255.0 diff --git a/venv/Lib/site-packages/pip/_vendor/rich/columns.py b/venv/Lib/site-packages/pip/_vendor/rich/columns.py new file mode 100644 index 0000000..669a3a7 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/columns.py @@ -0,0 +1,187 @@ +from collections import defaultdict +from itertools import chain +from operator import itemgetter +from typing import Dict, Iterable, List, Optional, Tuple + +from .align import Align, AlignMethod +from .console import Console, ConsoleOptions, RenderableType, RenderResult +from .constrain import Constrain +from .measure import Measurement +from .padding import Padding, PaddingDimensions +from .table import Table +from .text import TextType +from .jupyter import JupyterMixin + + +class Columns(JupyterMixin): + """Display renderables in neat columns. + + Args: + renderables (Iterable[RenderableType]): Any number of Rich renderables (including str). + width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None. + padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1). + expand (bool, optional): Expand columns to full width. Defaults to False. + equal (bool, optional): Arrange in to equal sized columns. Defaults to False. + column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False. + right_to_left (bool, optional): Start column from right hand side. Defaults to False. + align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None. + title (TextType, optional): Optional title for Columns. + """ + + def __init__( + self, + renderables: Optional[Iterable[RenderableType]] = None, + padding: PaddingDimensions = (0, 1), + *, + width: Optional[int] = None, + expand: bool = False, + equal: bool = False, + column_first: bool = False, + right_to_left: bool = False, + align: Optional[AlignMethod] = None, + title: Optional[TextType] = None, + ) -> None: + self.renderables = list(renderables or []) + self.width = width + self.padding = padding + self.expand = expand + self.equal = equal + self.column_first = column_first + self.right_to_left = right_to_left + self.align: Optional[AlignMethod] = align + self.title = title + + def add_renderable(self, renderable: RenderableType) -> None: + """Add a renderable to the columns. + + Args: + renderable (RenderableType): Any renderable object. + """ + self.renderables.append(renderable) + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + render_str = console.render_str + renderables = [ + render_str(renderable) if isinstance(renderable, str) else renderable + for renderable in self.renderables + ] + if not renderables: + return + _top, right, _bottom, left = Padding.unpack(self.padding) + width_padding = max(left, right) + max_width = options.max_width + widths: Dict[int, int] = defaultdict(int) + column_count = len(renderables) + + get_measurement = Measurement.get + renderable_widths = [ + get_measurement(console, options, renderable).maximum + for renderable in renderables + ] + if self.equal: + renderable_widths = [max(renderable_widths)] * len(renderable_widths) + + def iter_renderables( + column_count: int, + ) -> Iterable[Tuple[int, Optional[RenderableType]]]: + item_count = len(renderables) + if self.column_first: + width_renderables = list(zip(renderable_widths, renderables)) + + column_lengths: List[int] = [item_count // column_count] * column_count + for col_no in range(item_count % column_count): + column_lengths[col_no] += 1 + + row_count = (item_count + column_count - 1) // column_count + cells = [[-1] * column_count for _ in range(row_count)] + row = col = 0 + for index in range(item_count): + cells[row][col] = index + column_lengths[col] -= 1 + if column_lengths[col]: + row += 1 + else: + col += 1 + row = 0 + for index in chain.from_iterable(cells): + if index == -1: + break + yield width_renderables[index] + else: + yield from zip(renderable_widths, renderables) + # Pad odd elements with spaces + if item_count % column_count: + for _ in range(column_count - (item_count % column_count)): + yield 0, None + + table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False) + table.expand = self.expand + table.title = self.title + + if self.width is not None: + column_count = (max_width) // (self.width + width_padding) + for _ in range(column_count): + table.add_column(width=self.width) + else: + while column_count > 1: + widths.clear() + column_no = 0 + for renderable_width, _ in iter_renderables(column_count): + widths[column_no] = max(widths[column_no], renderable_width) + total_width = sum(widths.values()) + width_padding * ( + len(widths) - 1 + ) + if total_width > max_width: + column_count = len(widths) - 1 + break + else: + column_no = (column_no + 1) % column_count + else: + break + + get_renderable = itemgetter(1) + _renderables = [ + get_renderable(_renderable) + for _renderable in iter_renderables(column_count) + ] + if self.equal: + _renderables = [ + None + if renderable is None + else Constrain(renderable, renderable_widths[0]) + for renderable in _renderables + ] + if self.align: + align = self.align + _Align = Align + _renderables = [ + None if renderable is None else _Align(renderable, align) + for renderable in _renderables + ] + + right_to_left = self.right_to_left + add_row = table.add_row + for start in range(0, len(_renderables), column_count): + row = _renderables[start : start + column_count] + if right_to_left: + row = row[::-1] + add_row(*row) + yield table + + +if __name__ == "__main__": # pragma: no cover + import os + + console = Console() + + files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))] + columns = Columns(files, padding=(0, 1), expand=False, equal=False) + console.print(columns) + console.rule() + columns.column_first = True + console.print(columns) + columns.right_to_left = True + console.rule() + console.print(columns) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/console.py b/venv/Lib/site-packages/pip/_vendor/rich/console.py new file mode 100644 index 0000000..a11c7c1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/console.py @@ -0,0 +1,2633 @@ +import inspect +import os +import platform +import sys +import threading +import zlib +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from datetime import datetime +from functools import wraps +from getpass import getpass +from html import escape +from inspect import isclass +from itertools import islice +from math import ceil +from time import monotonic +from types import FrameType, ModuleType, TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterable, + List, + Mapping, + NamedTuple, + Optional, + TextIO, + Tuple, + Type, + Union, + cast, +) + +from pip._vendor.rich._null_file import NULL_FILE + +if sys.version_info >= (3, 8): + from typing import Literal, Protocol, runtime_checkable +else: + from pip._vendor.typing_extensions import ( + Literal, + Protocol, + runtime_checkable, + ) # pragma: no cover + +from . import errors, themes +from ._emoji_replace import _emoji_replace +from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT +from ._fileno import get_fileno +from ._log_render import FormatTimeCallable, LogRender +from .align import Align, AlignMethod +from .color import ColorSystem, blend_rgb +from .control import Control +from .emoji import EmojiVariant +from .highlighter import NullHighlighter, ReprHighlighter +from .markup import render as render_markup +from .measure import Measurement, measure_renderables +from .pager import Pager, SystemPager +from .pretty import Pretty, is_expandable +from .protocol import rich_cast +from .region import Region +from .scope import render_scope +from .screen import Screen +from .segment import Segment +from .style import Style, StyleType +from .styled import Styled +from .terminal_theme import DEFAULT_TERMINAL_THEME, SVG_EXPORT_THEME, TerminalTheme +from .text import Text, TextType +from .theme import Theme, ThemeStack + +if TYPE_CHECKING: + from ._windows import WindowsConsoleFeatures + from .live import Live + from .status import Status + +JUPYTER_DEFAULT_COLUMNS = 115 +JUPYTER_DEFAULT_LINES = 100 +WINDOWS = platform.system() == "Windows" + +HighlighterType = Callable[[Union[str, "Text"]], "Text"] +JustifyMethod = Literal["default", "left", "center", "right", "full"] +OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"] + + +class NoChange: + pass + + +NO_CHANGE = NoChange() + +try: + _STDIN_FILENO = sys.__stdin__.fileno() +except Exception: + _STDIN_FILENO = 0 +try: + _STDOUT_FILENO = sys.__stdout__.fileno() +except Exception: + _STDOUT_FILENO = 1 +try: + _STDERR_FILENO = sys.__stderr__.fileno() +except Exception: + _STDERR_FILENO = 2 + +_STD_STREAMS = (_STDIN_FILENO, _STDOUT_FILENO, _STDERR_FILENO) +_STD_STREAMS_OUTPUT = (_STDOUT_FILENO, _STDERR_FILENO) + + +_TERM_COLORS = { + "kitty": ColorSystem.EIGHT_BIT, + "256color": ColorSystem.EIGHT_BIT, + "16color": ColorSystem.STANDARD, +} + + +class ConsoleDimensions(NamedTuple): + """Size of the terminal.""" + + width: int + """The width of the console in 'cells'.""" + height: int + """The height of the console in lines.""" + + +@dataclass +class ConsoleOptions: + """Options for __rich_console__ method.""" + + size: ConsoleDimensions + """Size of console.""" + legacy_windows: bool + """legacy_windows: flag for legacy windows.""" + min_width: int + """Minimum width of renderable.""" + max_width: int + """Maximum width of renderable.""" + is_terminal: bool + """True if the target is a terminal, otherwise False.""" + encoding: str + """Encoding of terminal.""" + max_height: int + """Height of container (starts as terminal)""" + justify: Optional[JustifyMethod] = None + """Justify value override for renderable.""" + overflow: Optional[OverflowMethod] = None + """Overflow value override for renderable.""" + no_wrap: Optional[bool] = False + """Disable wrapping for text.""" + highlight: Optional[bool] = None + """Highlight override for render_str.""" + markup: Optional[bool] = None + """Enable markup when rendering strings.""" + height: Optional[int] = None + + @property + def ascii_only(self) -> bool: + """Check if renderables should use ascii only.""" + return not self.encoding.startswith("utf") + + def copy(self) -> "ConsoleOptions": + """Return a copy of the options. + + Returns: + ConsoleOptions: a copy of self. + """ + options: ConsoleOptions = ConsoleOptions.__new__(ConsoleOptions) + options.__dict__ = self.__dict__.copy() + return options + + def update( + self, + *, + width: Union[int, NoChange] = NO_CHANGE, + min_width: Union[int, NoChange] = NO_CHANGE, + max_width: Union[int, NoChange] = NO_CHANGE, + justify: Union[Optional[JustifyMethod], NoChange] = NO_CHANGE, + overflow: Union[Optional[OverflowMethod], NoChange] = NO_CHANGE, + no_wrap: Union[Optional[bool], NoChange] = NO_CHANGE, + highlight: Union[Optional[bool], NoChange] = NO_CHANGE, + markup: Union[Optional[bool], NoChange] = NO_CHANGE, + height: Union[Optional[int], NoChange] = NO_CHANGE, + ) -> "ConsoleOptions": + """Update values, return a copy.""" + options = self.copy() + if not isinstance(width, NoChange): + options.min_width = options.max_width = max(0, width) + if not isinstance(min_width, NoChange): + options.min_width = min_width + if not isinstance(max_width, NoChange): + options.max_width = max_width + if not isinstance(justify, NoChange): + options.justify = justify + if not isinstance(overflow, NoChange): + options.overflow = overflow + if not isinstance(no_wrap, NoChange): + options.no_wrap = no_wrap + if not isinstance(highlight, NoChange): + options.highlight = highlight + if not isinstance(markup, NoChange): + options.markup = markup + if not isinstance(height, NoChange): + if height is not None: + options.max_height = height + options.height = None if height is None else max(0, height) + return options + + def update_width(self, width: int) -> "ConsoleOptions": + """Update just the width, return a copy. + + Args: + width (int): New width (sets both min_width and max_width) + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.min_width = options.max_width = max(0, width) + return options + + def update_height(self, height: int) -> "ConsoleOptions": + """Update the height, and return a copy. + + Args: + height (int): New height + + Returns: + ~ConsoleOptions: New Console options instance. + """ + options = self.copy() + options.max_height = options.height = height + return options + + def reset_height(self) -> "ConsoleOptions": + """Return a copy of the options with height set to ``None``. + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.height = None + return options + + def update_dimensions(self, width: int, height: int) -> "ConsoleOptions": + """Update the width and height, and return a copy. + + Args: + width (int): New width (sets both min_width and max_width). + height (int): New height. + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.min_width = options.max_width = max(0, width) + options.height = options.max_height = height + return options + + +@runtime_checkable +class RichCast(Protocol): + """An object that may be 'cast' to a console renderable.""" + + def __rich__( + self, + ) -> Union["ConsoleRenderable", "RichCast", str]: # pragma: no cover + ... + + +@runtime_checkable +class ConsoleRenderable(Protocol): + """An object that supports the console protocol.""" + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": # pragma: no cover + ... + + +# A type that may be rendered by Console. +RenderableType = Union[ConsoleRenderable, RichCast, str] +"""A string or any object that may be rendered by Rich.""" + +# The result of calling a __rich_console__ method. +RenderResult = Iterable[Union[RenderableType, Segment]] + +_null_highlighter = NullHighlighter() + + +class CaptureError(Exception): + """An error in the Capture context manager.""" + + +class NewLine: + """A renderable to generate new line(s)""" + + def __init__(self, count: int = 1) -> None: + self.count = count + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> Iterable[Segment]: + yield Segment("\n" * self.count) + + +class ScreenUpdate: + """Render a list of lines at a given offset.""" + + def __init__(self, lines: List[List[Segment]], x: int, y: int) -> None: + self._lines = lines + self.x = x + self.y = y + + def __rich_console__( + self, console: "Console", options: ConsoleOptions + ) -> RenderResult: + x = self.x + move_to = Control.move_to + for offset, line in enumerate(self._lines, self.y): + yield move_to(x, offset) + yield from line + + +class Capture: + """Context manager to capture the result of printing to the console. + See :meth:`~rich.console.Console.capture` for how to use. + + Args: + console (Console): A console instance to capture output. + """ + + def __init__(self, console: "Console") -> None: + self._console = console + self._result: Optional[str] = None + + def __enter__(self) -> "Capture": + self._console.begin_capture() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self._result = self._console.end_capture() + + def get(self) -> str: + """Get the result of the capture.""" + if self._result is None: + raise CaptureError( + "Capture result is not available until context manager exits." + ) + return self._result + + +class ThemeContext: + """A context manager to use a temporary theme. See :meth:`~rich.console.Console.use_theme` for usage.""" + + def __init__(self, console: "Console", theme: Theme, inherit: bool = True) -> None: + self.console = console + self.theme = theme + self.inherit = inherit + + def __enter__(self) -> "ThemeContext": + self.console.push_theme(self.theme) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.console.pop_theme() + + +class PagerContext: + """A context manager that 'pages' content. See :meth:`~rich.console.Console.pager` for usage.""" + + def __init__( + self, + console: "Console", + pager: Optional[Pager] = None, + styles: bool = False, + links: bool = False, + ) -> None: + self._console = console + self.pager = SystemPager() if pager is None else pager + self.styles = styles + self.links = links + + def __enter__(self) -> "PagerContext": + self._console._enter_buffer() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + if exc_type is None: + with self._console._lock: + buffer: List[Segment] = self._console._buffer[:] + del self._console._buffer[:] + segments: Iterable[Segment] = buffer + if not self.styles: + segments = Segment.strip_styles(segments) + elif not self.links: + segments = Segment.strip_links(segments) + content = self._console._render_buffer(segments) + self.pager.show(content) + self._console._exit_buffer() + + +class ScreenContext: + """A context manager that enables an alternative screen. See :meth:`~rich.console.Console.screen` for usage.""" + + def __init__( + self, console: "Console", hide_cursor: bool, style: StyleType = "" + ) -> None: + self.console = console + self.hide_cursor = hide_cursor + self.screen = Screen(style=style) + self._changed = False + + def update( + self, *renderables: RenderableType, style: Optional[StyleType] = None + ) -> None: + """Update the screen. + + Args: + renderable (RenderableType, optional): Optional renderable to replace current renderable, + or None for no change. Defaults to None. + style: (Style, optional): Replacement style, or None for no change. Defaults to None. + """ + if renderables: + self.screen.renderable = ( + Group(*renderables) if len(renderables) > 1 else renderables[0] + ) + if style is not None: + self.screen.style = style + self.console.print(self.screen, end="") + + def __enter__(self) -> "ScreenContext": + self._changed = self.console.set_alt_screen(True) + if self._changed and self.hide_cursor: + self.console.show_cursor(False) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + if self._changed: + self.console.set_alt_screen(False) + if self.hide_cursor: + self.console.show_cursor(True) + + +class Group: + """Takes a group of renderables and returns a renderable object that renders the group. + + Args: + renderables (Iterable[RenderableType]): An iterable of renderable objects. + fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. + """ + + def __init__(self, *renderables: "RenderableType", fit: bool = True) -> None: + self._renderables = renderables + self.fit = fit + self._render: Optional[List[RenderableType]] = None + + @property + def renderables(self) -> List["RenderableType"]: + if self._render is None: + self._render = list(self._renderables) + return self._render + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + if self.fit: + return measure_renderables(console, options, self.renderables) + else: + return Measurement(options.max_width, options.max_width) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> RenderResult: + yield from self.renderables + + +def group(fit: bool = True) -> Callable[..., Callable[..., Group]]: + """A decorator that turns an iterable of renderables in to a group. + + Args: + fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. + """ + + def decorator( + method: Callable[..., Iterable[RenderableType]] + ) -> Callable[..., Group]: + """Convert a method that returns an iterable of renderables in to a Group.""" + + @wraps(method) + def _replace(*args: Any, **kwargs: Any) -> Group: + renderables = method(*args, **kwargs) + return Group(*renderables, fit=fit) + + return _replace + + return decorator + + +def _is_jupyter() -> bool: # pragma: no cover + """Check if we're running in a Jupyter notebook.""" + try: + get_ipython # type: ignore[name-defined] + except NameError: + return False + ipython = get_ipython() # type: ignore[name-defined] + shell = ipython.__class__.__name__ + if ( + "google.colab" in str(ipython.__class__) + or os.getenv("DATABRICKS_RUNTIME_VERSION") + or shell == "ZMQInteractiveShell" + ): + return True # Jupyter notebook or qtconsole + elif shell == "TerminalInteractiveShell": + return False # Terminal running IPython + else: + return False # Other type (?) + + +COLOR_SYSTEMS = { + "standard": ColorSystem.STANDARD, + "256": ColorSystem.EIGHT_BIT, + "truecolor": ColorSystem.TRUECOLOR, + "windows": ColorSystem.WINDOWS, +} + +_COLOR_SYSTEMS_NAMES = {system: name for name, system in COLOR_SYSTEMS.items()} + + +@dataclass +class ConsoleThreadLocals(threading.local): + """Thread local values for Console context.""" + + theme_stack: ThemeStack + buffer: List[Segment] = field(default_factory=list) + buffer_index: int = 0 + + +class RenderHook(ABC): + """Provides hooks in to the render process.""" + + @abstractmethod + def process_renderables( + self, renderables: List[ConsoleRenderable] + ) -> List[ConsoleRenderable]: + """Called with a list of objects to render. + + This method can return a new list of renderables, or modify and return the same list. + + Args: + renderables (List[ConsoleRenderable]): A number of renderable objects. + + Returns: + List[ConsoleRenderable]: A replacement list of renderables. + """ + + +_windows_console_features: Optional["WindowsConsoleFeatures"] = None + + +def get_windows_console_features() -> "WindowsConsoleFeatures": # pragma: no cover + global _windows_console_features + if _windows_console_features is not None: + return _windows_console_features + from ._windows import get_windows_console_features + + _windows_console_features = get_windows_console_features() + return _windows_console_features + + +def detect_legacy_windows() -> bool: + """Detect legacy Windows.""" + return WINDOWS and not get_windows_console_features().vt + + +class Console: + """A high level console interface. + + Args: + color_system (str, optional): The color system supported by your terminal, + either ``"standard"``, ``"256"`` or ``"truecolor"``. Leave as ``"auto"`` to autodetect. + force_terminal (Optional[bool], optional): Enable/disable terminal control codes, or None to auto-detect terminal. Defaults to None. + force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None. + force_interactive (Optional[bool], optional): Enable/disable interactive mode, or None to auto detect. Defaults to None. + soft_wrap (Optional[bool], optional): Set soft wrap default on print method. Defaults to False. + theme (Theme, optional): An optional style theme object, or ``None`` for default theme. + stderr (bool, optional): Use stderr rather than stdout if ``file`` is not specified. Defaults to False. + file (IO, optional): A file object where the console should write to. Defaults to stdout. + quiet (bool, Optional): Boolean to suppress all output. Defaults to False. + width (int, optional): The width of the terminal. Leave as default to auto-detect width. + height (int, optional): The height of the terminal. Leave as default to auto-detect height. + style (StyleType, optional): Style to apply to all output, or None for no style. Defaults to None. + no_color (Optional[bool], optional): Enabled no color mode, or None to auto detect. Defaults to None. + tab_size (int, optional): Number of spaces used to replace a tab character. Defaults to 8. + record (bool, optional): Boolean to enable recording of terminal output, + required to call :meth:`export_html`, :meth:`export_svg`, and :meth:`export_text`. Defaults to False. + markup (bool, optional): Boolean to enable :ref:`console_markup`. Defaults to True. + emoji (bool, optional): Enable emoji code. Defaults to True. + emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. + highlight (bool, optional): Enable automatic highlighting. Defaults to True. + log_time (bool, optional): Boolean to enable logging of time by :meth:`log` methods. Defaults to True. + log_path (bool, optional): Boolean to enable the logging of the caller by :meth:`log`. Defaults to True. + log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%X] ". + highlighter (HighlighterType, optional): Default highlighter. + legacy_windows (bool, optional): Enable legacy Windows mode, or ``None`` to auto detect. Defaults to ``None``. + safe_box (bool, optional): Restrict box options that don't render on legacy Windows. + get_datetime (Callable[[], datetime], optional): Callable that gets the current time as a datetime.datetime object (used by Console.log), + or None for datetime.now. + get_time (Callable[[], time], optional): Callable that gets the current time in seconds, default uses time.monotonic. + """ + + _environ: Mapping[str, str] = os.environ + + def __init__( + self, + *, + color_system: Optional[ + Literal["auto", "standard", "256", "truecolor", "windows"] + ] = "auto", + force_terminal: Optional[bool] = None, + force_jupyter: Optional[bool] = None, + force_interactive: Optional[bool] = None, + soft_wrap: bool = False, + theme: Optional[Theme] = None, + stderr: bool = False, + file: Optional[IO[str]] = None, + quiet: bool = False, + width: Optional[int] = None, + height: Optional[int] = None, + style: Optional[StyleType] = None, + no_color: Optional[bool] = None, + tab_size: int = 8, + record: bool = False, + markup: bool = True, + emoji: bool = True, + emoji_variant: Optional[EmojiVariant] = None, + highlight: bool = True, + log_time: bool = True, + log_path: bool = True, + log_time_format: Union[str, FormatTimeCallable] = "[%X]", + highlighter: Optional["HighlighterType"] = ReprHighlighter(), + legacy_windows: Optional[bool] = None, + safe_box: bool = True, + get_datetime: Optional[Callable[[], datetime]] = None, + get_time: Optional[Callable[[], float]] = None, + _environ: Optional[Mapping[str, str]] = None, + ): + # Copy of os.environ allows us to replace it for testing + if _environ is not None: + self._environ = _environ + + self.is_jupyter = _is_jupyter() if force_jupyter is None else force_jupyter + if self.is_jupyter: + if width is None: + jupyter_columns = self._environ.get("JUPYTER_COLUMNS") + if jupyter_columns is not None and jupyter_columns.isdigit(): + width = int(jupyter_columns) + else: + width = JUPYTER_DEFAULT_COLUMNS + if height is None: + jupyter_lines = self._environ.get("JUPYTER_LINES") + if jupyter_lines is not None and jupyter_lines.isdigit(): + height = int(jupyter_lines) + else: + height = JUPYTER_DEFAULT_LINES + + self.tab_size = tab_size + self.record = record + self._markup = markup + self._emoji = emoji + self._emoji_variant: Optional[EmojiVariant] = emoji_variant + self._highlight = highlight + self.legacy_windows: bool = ( + (detect_legacy_windows() and not self.is_jupyter) + if legacy_windows is None + else legacy_windows + ) + + if width is None: + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) - self.legacy_windows + if height is None: + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + + self.soft_wrap = soft_wrap + self._width = width + self._height = height + + self._color_system: Optional[ColorSystem] + + self._force_terminal = None + if force_terminal is not None: + self._force_terminal = force_terminal + + self._file = file + self.quiet = quiet + self.stderr = stderr + + if color_system is None: + self._color_system = None + elif color_system == "auto": + self._color_system = self._detect_color_system() + else: + self._color_system = COLOR_SYSTEMS[color_system] + + self._lock = threading.RLock() + self._log_render = LogRender( + show_time=log_time, + show_path=log_path, + time_format=log_time_format, + ) + self.highlighter: HighlighterType = highlighter or _null_highlighter + self.safe_box = safe_box + self.get_datetime = get_datetime or datetime.now + self.get_time = get_time or monotonic + self.style = style + self.no_color = ( + no_color if no_color is not None else "NO_COLOR" in self._environ + ) + self.is_interactive = ( + (self.is_terminal and not self.is_dumb_terminal) + if force_interactive is None + else force_interactive + ) + + self._record_buffer_lock = threading.RLock() + self._thread_locals = ConsoleThreadLocals( + theme_stack=ThemeStack(themes.DEFAULT if theme is None else theme) + ) + self._record_buffer: List[Segment] = [] + self._render_hooks: List[RenderHook] = [] + self._live: Optional["Live"] = None + self._is_alt_screen = False + + def __repr__(self) -> str: + return f"" + + @property + def file(self) -> IO[str]: + """Get the file object to write to.""" + file = self._file or (sys.stderr if self.stderr else sys.stdout) + file = getattr(file, "rich_proxied_file", file) + if file is None: + file = NULL_FILE + return file + + @file.setter + def file(self, new_file: IO[str]) -> None: + """Set a new file object.""" + self._file = new_file + + @property + def _buffer(self) -> List[Segment]: + """Get a thread local buffer.""" + return self._thread_locals.buffer + + @property + def _buffer_index(self) -> int: + """Get a thread local buffer.""" + return self._thread_locals.buffer_index + + @_buffer_index.setter + def _buffer_index(self, value: int) -> None: + self._thread_locals.buffer_index = value + + @property + def _theme_stack(self) -> ThemeStack: + """Get the thread local theme stack.""" + return self._thread_locals.theme_stack + + def _detect_color_system(self) -> Optional[ColorSystem]: + """Detect color system from env vars.""" + if self.is_jupyter: + return ColorSystem.TRUECOLOR + if not self.is_terminal or self.is_dumb_terminal: + return None + if WINDOWS: # pragma: no cover + if self.legacy_windows: # pragma: no cover + return ColorSystem.WINDOWS + windows_console_features = get_windows_console_features() + return ( + ColorSystem.TRUECOLOR + if windows_console_features.truecolor + else ColorSystem.EIGHT_BIT + ) + else: + color_term = self._environ.get("COLORTERM", "").strip().lower() + if color_term in ("truecolor", "24bit"): + return ColorSystem.TRUECOLOR + term = self._environ.get("TERM", "").strip().lower() + _term_name, _hyphen, colors = term.rpartition("-") + color_system = _TERM_COLORS.get(colors, ColorSystem.STANDARD) + return color_system + + def _enter_buffer(self) -> None: + """Enter in to a buffer context, and buffer all output.""" + self._buffer_index += 1 + + def _exit_buffer(self) -> None: + """Leave buffer context, and render content if required.""" + self._buffer_index -= 1 + self._check_buffer() + + def set_live(self, live: "Live") -> None: + """Set Live instance. Used by Live context manager. + + Args: + live (Live): Live instance using this Console. + + Raises: + errors.LiveError: If this Console has a Live context currently active. + """ + with self._lock: + if self._live is not None: + raise errors.LiveError("Only one live display may be active at once") + self._live = live + + def clear_live(self) -> None: + """Clear the Live instance.""" + with self._lock: + self._live = None + + def push_render_hook(self, hook: RenderHook) -> None: + """Add a new render hook to the stack. + + Args: + hook (RenderHook): Render hook instance. + """ + with self._lock: + self._render_hooks.append(hook) + + def pop_render_hook(self) -> None: + """Pop the last renderhook from the stack.""" + with self._lock: + self._render_hooks.pop() + + def __enter__(self) -> "Console": + """Own context manager to enter buffer context.""" + self._enter_buffer() + return self + + def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: + """Exit buffer context.""" + self._exit_buffer() + + def begin_capture(self) -> None: + """Begin capturing console output. Call :meth:`end_capture` to exit capture mode and return output.""" + self._enter_buffer() + + def end_capture(self) -> str: + """End capture mode and return captured string. + + Returns: + str: Console output. + """ + render_result = self._render_buffer(self._buffer) + del self._buffer[:] + self._exit_buffer() + return render_result + + def push_theme(self, theme: Theme, *, inherit: bool = True) -> None: + """Push a new theme on to the top of the stack, replacing the styles from the previous theme. + Generally speaking, you should call :meth:`~rich.console.Console.use_theme` to get a context manager, rather + than calling this method directly. + + Args: + theme (Theme): A theme instance. + inherit (bool, optional): Inherit existing styles. Defaults to True. + """ + self._theme_stack.push_theme(theme, inherit=inherit) + + def pop_theme(self) -> None: + """Remove theme from top of stack, restoring previous theme.""" + self._theme_stack.pop_theme() + + def use_theme(self, theme: Theme, *, inherit: bool = True) -> ThemeContext: + """Use a different theme for the duration of the context manager. + + Args: + theme (Theme): Theme instance to user. + inherit (bool, optional): Inherit existing console styles. Defaults to True. + + Returns: + ThemeContext: [description] + """ + return ThemeContext(self, theme, inherit) + + @property + def color_system(self) -> Optional[str]: + """Get color system string. + + Returns: + Optional[str]: "standard", "256" or "truecolor". + """ + + if self._color_system is not None: + return _COLOR_SYSTEMS_NAMES[self._color_system] + else: + return None + + @property + def encoding(self) -> str: + """Get the encoding of the console file, e.g. ``"utf-8"``. + + Returns: + str: A standard encoding string. + """ + return (getattr(self.file, "encoding", "utf-8") or "utf-8").lower() + + @property + def is_terminal(self) -> bool: + """Check if the console is writing to a terminal. + + Returns: + bool: True if the console writing to a device capable of + understanding terminal codes, otherwise False. + """ + if self._force_terminal is not None: + return self._force_terminal + + if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith( + "idlelib" + ): + # Return False for Idle which claims to be a tty but can't handle ansi codes + return False + + if self.is_jupyter: + # return False for Jupyter, which may have FORCE_COLOR set + return False + + # If FORCE_COLOR env var has any value at all, we assume a terminal. + force_color = self._environ.get("FORCE_COLOR") + if force_color is not None: + self._force_terminal = True + return True + + isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None) + try: + return False if isatty is None else isatty() + except ValueError: + # in some situation (at the end of a pytest run for example) isatty() can raise + # ValueError: I/O operation on closed file + # return False because we aren't in a terminal anymore + return False + + @property + def is_dumb_terminal(self) -> bool: + """Detect dumb terminal. + + Returns: + bool: True if writing to a dumb terminal, otherwise False. + + """ + _term = self._environ.get("TERM", "") + is_dumb = _term.lower() in ("dumb", "unknown") + return self.is_terminal and is_dumb + + @property + def options(self) -> ConsoleOptions: + """Get default console options.""" + return ConsoleOptions( + max_height=self.size.height, + size=self.size, + legacy_windows=self.legacy_windows, + min_width=1, + max_width=self.width, + encoding=self.encoding, + is_terminal=self.is_terminal, + ) + + @property + def size(self) -> ConsoleDimensions: + """Get the size of the console. + + Returns: + ConsoleDimensions: A named tuple containing the dimensions. + """ + + if self._width is not None and self._height is not None: + return ConsoleDimensions(self._width - self.legacy_windows, self._height) + + if self.is_dumb_terminal: + return ConsoleDimensions(80, 25) + + width: Optional[int] = None + height: Optional[int] = None + + if WINDOWS: # pragma: no cover + try: + width, height = os.get_terminal_size() + except (AttributeError, ValueError, OSError): # Probably not a terminal + pass + else: + for file_descriptor in _STD_STREAMS: + try: + width, height = os.get_terminal_size(file_descriptor) + except (AttributeError, ValueError, OSError): + pass + else: + break + + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + + # get_terminal_size can report 0, 0 if run from pseudo-terminal + width = width or 80 + height = height or 25 + return ConsoleDimensions( + width - self.legacy_windows if self._width is None else self._width, + height if self._height is None else self._height, + ) + + @size.setter + def size(self, new_size: Tuple[int, int]) -> None: + """Set a new size for the terminal. + + Args: + new_size (Tuple[int, int]): New width and height. + """ + width, height = new_size + self._width = width + self._height = height + + @property + def width(self) -> int: + """Get the width of the console. + + Returns: + int: The width (in characters) of the console. + """ + return self.size.width + + @width.setter + def width(self, width: int) -> None: + """Set width. + + Args: + width (int): New width. + """ + self._width = width + + @property + def height(self) -> int: + """Get the height of the console. + + Returns: + int: The height (in lines) of the console. + """ + return self.size.height + + @height.setter + def height(self, height: int) -> None: + """Set height. + + Args: + height (int): new height. + """ + self._height = height + + def bell(self) -> None: + """Play a 'bell' sound (if supported by the terminal).""" + self.control(Control.bell()) + + def capture(self) -> Capture: + """A context manager to *capture* the result of print() or log() in a string, + rather than writing it to the console. + + Example: + >>> from rich.console import Console + >>> console = Console() + >>> with console.capture() as capture: + ... console.print("[bold magenta]Hello World[/]") + >>> print(capture.get()) + + Returns: + Capture: Context manager with disables writing to the terminal. + """ + capture = Capture(self) + return capture + + def pager( + self, pager: Optional[Pager] = None, styles: bool = False, links: bool = False + ) -> PagerContext: + """A context manager to display anything printed within a "pager". The pager application + is defined by the system and will typically support at least pressing a key to scroll. + + Args: + pager (Pager, optional): A pager object, or None to use :class:`~rich.pager.SystemPager`. Defaults to None. + styles (bool, optional): Show styles in pager. Defaults to False. + links (bool, optional): Show links in pager. Defaults to False. + + Example: + >>> from rich.console import Console + >>> from rich.__main__ import make_test_card + >>> console = Console() + >>> with console.pager(): + console.print(make_test_card()) + + Returns: + PagerContext: A context manager. + """ + return PagerContext(self, pager=pager, styles=styles, links=links) + + def line(self, count: int = 1) -> None: + """Write new line(s). + + Args: + count (int, optional): Number of new lines. Defaults to 1. + """ + + assert count >= 0, "count must be >= 0" + self.print(NewLine(count)) + + def clear(self, home: bool = True) -> None: + """Clear the screen. + + Args: + home (bool, optional): Also move the cursor to 'home' position. Defaults to True. + """ + if home: + self.control(Control.clear(), Control.home()) + else: + self.control(Control.clear()) + + def status( + self, + status: RenderableType, + *, + spinner: str = "dots", + spinner_style: StyleType = "status.spinner", + speed: float = 1.0, + refresh_per_second: float = 12.5, + ) -> "Status": + """Display a status and spinner. + + Args: + status (RenderableType): A status renderable (str or Text typically). + spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots". + spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner". + speed (float, optional): Speed factor for spinner animation. Defaults to 1.0. + refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5. + + Returns: + Status: A Status object that may be used as a context manager. + """ + from .status import Status + + status_renderable = Status( + status, + console=self, + spinner=spinner, + spinner_style=spinner_style, + speed=speed, + refresh_per_second=refresh_per_second, + ) + return status_renderable + + def show_cursor(self, show: bool = True) -> bool: + """Show or hide the cursor. + + Args: + show (bool, optional): Set visibility of the cursor. + """ + if self.is_terminal: + self.control(Control.show_cursor(show)) + return True + return False + + def set_alt_screen(self, enable: bool = True) -> bool: + """Enables alternative screen mode. + + Note, if you enable this mode, you should ensure that is disabled before + the application exits. See :meth:`~rich.Console.screen` for a context manager + that handles this for you. + + Args: + enable (bool, optional): Enable (True) or disable (False) alternate screen. Defaults to True. + + Returns: + bool: True if the control codes were written. + + """ + changed = False + if self.is_terminal and not self.legacy_windows: + self.control(Control.alt_screen(enable)) + changed = True + self._is_alt_screen = enable + return changed + + @property + def is_alt_screen(self) -> bool: + """Check if the alt screen was enabled. + + Returns: + bool: True if the alt screen was enabled, otherwise False. + """ + return self._is_alt_screen + + def set_window_title(self, title: str) -> bool: + """Set the title of the console terminal window. + + Warning: There is no means within Rich of "resetting" the window title to its + previous value, meaning the title you set will persist even after your application + exits. + + ``fish`` shell resets the window title before and after each command by default, + negating this issue. Windows Terminal and command prompt will also reset the title for you. + Most other shells and terminals, however, do not do this. + + Some terminals may require configuration changes before you can set the title. + Some terminals may not support setting the title at all. + + Other software (including the terminal itself, the shell, custom prompts, plugins, etc.) + may also set the terminal window title. This could result in whatever value you write + using this method being overwritten. + + Args: + title (str): The new title of the terminal window. + + Returns: + bool: True if the control code to change the terminal title was + written, otherwise False. Note that a return value of True + does not guarantee that the window title has actually changed, + since the feature may be unsupported/disabled in some terminals. + """ + if self.is_terminal: + self.control(Control.title(title)) + return True + return False + + def screen( + self, hide_cursor: bool = True, style: Optional[StyleType] = None + ) -> "ScreenContext": + """Context manager to enable and disable 'alternative screen' mode. + + Args: + hide_cursor (bool, optional): Also hide the cursor. Defaults to False. + style (Style, optional): Optional style for screen. Defaults to None. + + Returns: + ~ScreenContext: Context which enables alternate screen on enter, and disables it on exit. + """ + return ScreenContext(self, hide_cursor=hide_cursor, style=style or "") + + def measure( + self, renderable: RenderableType, *, options: Optional[ConsoleOptions] = None + ) -> Measurement: + """Measure a renderable. Returns a :class:`~rich.measure.Measurement` object which contains + information regarding the number of characters required to print the renderable. + + Args: + renderable (RenderableType): Any renderable or string. + options (Optional[ConsoleOptions], optional): Options to use when measuring, or None + to use default options. Defaults to None. + + Returns: + Measurement: A measurement of the renderable. + """ + measurement = Measurement.get(self, options or self.options, renderable) + return measurement + + def render( + self, renderable: RenderableType, options: Optional[ConsoleOptions] = None + ) -> Iterable[Segment]: + """Render an object in to an iterable of `Segment` instances. + + This method contains the logic for rendering objects with the console protocol. + You are unlikely to need to use it directly, unless you are extending the library. + + Args: + renderable (RenderableType): An object supporting the console protocol, or + an object that may be converted to a string. + options (ConsoleOptions, optional): An options object, or None to use self.options. Defaults to None. + + Returns: + Iterable[Segment]: An iterable of segments that may be rendered. + """ + + _options = options or self.options + if _options.max_width < 1: + # No space to render anything. This prevents potential recursion errors. + return + render_iterable: RenderResult + + renderable = rich_cast(renderable) + if hasattr(renderable, "__rich_console__") and not isclass(renderable): + render_iterable = renderable.__rich_console__(self, _options) # type: ignore[union-attr] + elif isinstance(renderable, str): + text_renderable = self.render_str( + renderable, highlight=_options.highlight, markup=_options.markup + ) + render_iterable = text_renderable.__rich_console__(self, _options) + else: + raise errors.NotRenderableError( + f"Unable to render {renderable!r}; " + "A str, Segment or object with __rich_console__ method is required" + ) + + try: + iter_render = iter(render_iterable) + except TypeError: + raise errors.NotRenderableError( + f"object {render_iterable!r} is not renderable" + ) + _Segment = Segment + _options = _options.reset_height() + for render_output in iter_render: + if isinstance(render_output, _Segment): + yield render_output + else: + yield from self.render(render_output, _options) + + def render_lines( + self, + renderable: RenderableType, + options: Optional[ConsoleOptions] = None, + *, + style: Optional[Style] = None, + pad: bool = True, + new_lines: bool = False, + ) -> List[List[Segment]]: + """Render objects in to a list of lines. + + The output of render_lines is useful when further formatting of rendered console text + is required, such as the Panel class which draws a border around any renderable object. + + Args: + renderable (RenderableType): Any object renderable in the console. + options (Optional[ConsoleOptions], optional): Console options, or None to use self.options. Default to ``None``. + style (Style, optional): Optional style to apply to renderables. Defaults to ``None``. + pad (bool, optional): Pad lines shorter than render width. Defaults to ``True``. + new_lines (bool, optional): Include "\n" characters at end of lines. + + Returns: + List[List[Segment]]: A list of lines, where a line is a list of Segment objects. + """ + with self._lock: + render_options = options or self.options + _rendered = self.render(renderable, render_options) + if style: + _rendered = Segment.apply_style(_rendered, style) + + render_height = render_options.height + if render_height is not None: + render_height = max(0, render_height) + + lines = list( + islice( + Segment.split_and_crop_lines( + _rendered, + render_options.max_width, + include_new_lines=new_lines, + pad=pad, + style=style, + ), + None, + render_height, + ) + ) + if render_options.height is not None: + extra_lines = render_options.height - len(lines) + if extra_lines > 0: + pad_line = [ + [Segment(" " * render_options.max_width, style), Segment("\n")] + if new_lines + else [Segment(" " * render_options.max_width, style)] + ] + lines.extend(pad_line * extra_lines) + + return lines + + def render_str( + self, + text: str, + *, + style: Union[str, Style] = "", + justify: Optional[JustifyMethod] = None, + overflow: Optional[OverflowMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + highlighter: Optional[HighlighterType] = None, + ) -> "Text": + """Convert a string to a Text instance. This is called automatically if + you print or log a string. + + Args: + text (str): Text to render. + style (Union[str, Style], optional): Style to apply to rendered text. + justify (str, optional): Justify method: "default", "left", "center", "full", or "right". Defaults to ``None``. + overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji, or ``None`` to use Console default. + markup (Optional[bool], optional): Enable markup, or ``None`` to use Console default. + highlight (Optional[bool], optional): Enable highlighting, or ``None`` to use Console default. + highlighter (HighlighterType, optional): Optional highlighter to apply. + Returns: + ConsoleRenderable: Renderable object. + + """ + emoji_enabled = emoji or (emoji is None and self._emoji) + markup_enabled = markup or (markup is None and self._markup) + highlight_enabled = highlight or (highlight is None and self._highlight) + + if markup_enabled: + rich_text = render_markup( + text, + style=style, + emoji=emoji_enabled, + emoji_variant=self._emoji_variant, + ) + rich_text.justify = justify + rich_text.overflow = overflow + else: + rich_text = Text( + _emoji_replace(text, default_variant=self._emoji_variant) + if emoji_enabled + else text, + justify=justify, + overflow=overflow, + style=style, + ) + + _highlighter = (highlighter or self.highlighter) if highlight_enabled else None + if _highlighter is not None: + highlight_text = _highlighter(str(rich_text)) + highlight_text.copy_styles(rich_text) + return highlight_text + + return rich_text + + def get_style( + self, name: Union[str, Style], *, default: Optional[Union[Style, str]] = None + ) -> Style: + """Get a Style instance by its theme name or parse a definition. + + Args: + name (str): The name of a style or a style definition. + + Returns: + Style: A Style object. + + Raises: + MissingStyle: If no style could be parsed from name. + + """ + if isinstance(name, Style): + return name + + try: + style = self._theme_stack.get(name) + if style is None: + style = Style.parse(name) + return style.copy() if style.link else style + except errors.StyleSyntaxError as error: + if default is not None: + return self.get_style(default) + raise errors.MissingStyle( + f"Failed to get style {name!r}; {error}" + ) from None + + def _collect_renderables( + self, + objects: Iterable[Any], + sep: str, + end: str, + *, + justify: Optional[JustifyMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + ) -> List[ConsoleRenderable]: + """Combine a number of renderables and text into one renderable. + + Args: + objects (Iterable[Any]): Anything that Rich can render. + sep (str): String to write between print data. + end (str): String to write at end of print data. + justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. + + Returns: + List[ConsoleRenderable]: A list of things to render. + """ + renderables: List[ConsoleRenderable] = [] + _append = renderables.append + text: List[Text] = [] + append_text = text.append + + append = _append + if justify in ("left", "center", "right"): + + def align_append(renderable: RenderableType) -> None: + _append(Align(renderable, cast(AlignMethod, justify))) + + append = align_append + + _highlighter: HighlighterType = _null_highlighter + if highlight or (highlight is None and self._highlight): + _highlighter = self.highlighter + + def check_text() -> None: + if text: + sep_text = Text(sep, justify=justify, end=end) + append(sep_text.join(text)) + text.clear() + + for renderable in objects: + renderable = rich_cast(renderable) + if isinstance(renderable, str): + append_text( + self.render_str( + renderable, emoji=emoji, markup=markup, highlighter=_highlighter + ) + ) + elif isinstance(renderable, Text): + append_text(renderable) + elif isinstance(renderable, ConsoleRenderable): + check_text() + append(renderable) + elif is_expandable(renderable): + check_text() + append(Pretty(renderable, highlighter=_highlighter)) + else: + append_text(_highlighter(str(renderable))) + + check_text() + + if self.style is not None: + style = self.get_style(self.style) + renderables = [Styled(renderable, style) for renderable in renderables] + + return renderables + + def rule( + self, + title: TextType = "", + *, + characters: str = "─", + style: Union[str, Style] = "rule.line", + align: AlignMethod = "center", + ) -> None: + """Draw a line with optional centered title. + + Args: + title (str, optional): Text to render over the rule. Defaults to "". + characters (str, optional): Character(s) to form the line. Defaults to "─". + style (str, optional): Style of line. Defaults to "rule.line". + align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center". + """ + from .rule import Rule + + rule = Rule(title=title, characters=characters, style=style, align=align) + self.print(rule) + + def control(self, *control: Control) -> None: + """Insert non-printing control codes. + + Args: + control_codes (str): Control codes, such as those that may move the cursor. + """ + if not self.is_dumb_terminal: + with self: + self._buffer.extend(_control.segment for _control in control) + + def out( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + highlight: Optional[bool] = None, + ) -> None: + """Output to the terminal. This is a low-level way of writing to the terminal which unlike + :meth:`~rich.console.Console.print` won't pretty print, wrap text, or apply markup, but will + optionally apply highlighting and a basic style. + + Args: + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use + console default. Defaults to ``None``. + """ + raw_output: str = sep.join(str(_object) for _object in objects) + self.print( + raw_output, + style=style, + highlight=highlight, + emoji=False, + markup=False, + no_wrap=True, + overflow="ignore", + crop=False, + end=end, + ) + + def print( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + justify: Optional[JustifyMethod] = None, + overflow: Optional[OverflowMethod] = None, + no_wrap: Optional[bool] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + width: Optional[int] = None, + height: Optional[int] = None, + crop: bool = True, + soft_wrap: Optional[bool] = None, + new_line_start: bool = False, + ) -> None: + """Print to the console. + + Args: + objects (positional args): Objects to log to the terminal. + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + justify (str, optional): Justify method: "default", "left", "right", "center", or "full". Defaults to ``None``. + overflow (str, optional): Overflow method: "ignore", "crop", "fold", or "ellipsis". Defaults to None. + no_wrap (Optional[bool], optional): Disable word wrapping. Defaults to None. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to ``None``. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to ``None``. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``. + width (Optional[int], optional): Width of output, or ``None`` to auto-detect. Defaults to ``None``. + crop (Optional[bool], optional): Crop output to width of terminal. Defaults to True. + soft_wrap (bool, optional): Enable soft wrap mode which disables word wrapping and cropping of text or ``None`` for + Console default. Defaults to ``None``. + new_line_start (bool, False): Insert a new line at the start if the output contains more than one line. Defaults to ``False``. + """ + if not objects: + objects = (NewLine(),) + + if soft_wrap is None: + soft_wrap = self.soft_wrap + if soft_wrap: + if no_wrap is None: + no_wrap = True + if overflow is None: + overflow = "ignore" + crop = False + render_hooks = self._render_hooks[:] + with self: + renderables = self._collect_renderables( + objects, + sep, + end, + justify=justify, + emoji=emoji, + markup=markup, + highlight=highlight, + ) + for hook in render_hooks: + renderables = hook.process_renderables(renderables) + render_options = self.options.update( + justify=justify, + overflow=overflow, + width=min(width, self.width) if width is not None else NO_CHANGE, + height=height, + no_wrap=no_wrap, + markup=markup, + highlight=highlight, + ) + + new_segments: List[Segment] = [] + extend = new_segments.extend + render = self.render + if style is None: + for renderable in renderables: + extend(render(renderable, render_options)) + else: + for renderable in renderables: + extend( + Segment.apply_style( + render(renderable, render_options), self.get_style(style) + ) + ) + if new_line_start: + if ( + len("".join(segment.text for segment in new_segments).splitlines()) + > 1 + ): + new_segments.insert(0, Segment.line()) + if crop: + buffer_extend = self._buffer.extend + for line in Segment.split_and_crop_lines( + new_segments, self.width, pad=False + ): + buffer_extend(line) + else: + self._buffer.extend(new_segments) + + def print_json( + self, + json: Optional[str] = None, + *, + data: Any = None, + indent: Union[None, int, str] = 2, + highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = False, + check_circular: bool = True, + allow_nan: bool = True, + default: Optional[Callable[[Any], Any]] = None, + sort_keys: bool = False, + ) -> None: + """Pretty prints JSON. Output will be valid JSON. + + Args: + json (Optional[str]): A string containing JSON. + data (Any): If json is not supplied, then encode this data. + indent (Union[None, int, str], optional): Number of spaces to indent. Defaults to 2. + highlight (bool, optional): Enable highlighting of output: Defaults to True. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. + """ + from pip._vendor.rich.json import JSON + + if json is None: + json_renderable = JSON.from_data( + data, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) + else: + if not isinstance(json, str): + raise TypeError( + f"json must be str. Did you mean print_json(data={json!r}) ?" + ) + json_renderable = JSON( + json, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) + self.print(json_renderable, soft_wrap=True) + + def update_screen( + self, + renderable: RenderableType, + *, + region: Optional[Region] = None, + options: Optional[ConsoleOptions] = None, + ) -> None: + """Update the screen at a given offset. + + Args: + renderable (RenderableType): A Rich renderable. + region (Region, optional): Region of screen to update, or None for entire screen. Defaults to None. + x (int, optional): x offset. Defaults to 0. + y (int, optional): y offset. Defaults to 0. + + Raises: + errors.NoAltScreen: If the Console isn't in alt screen mode. + + """ + if not self.is_alt_screen: + raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") + render_options = options or self.options + if region is None: + x = y = 0 + render_options = render_options.update_dimensions( + render_options.max_width, render_options.height or self.height + ) + else: + x, y, width, height = region + render_options = render_options.update_dimensions(width, height) + + lines = self.render_lines(renderable, options=render_options) + self.update_screen_lines(lines, x, y) + + def update_screen_lines( + self, lines: List[List[Segment]], x: int = 0, y: int = 0 + ) -> None: + """Update lines of the screen at a given offset. + + Args: + lines (List[List[Segment]]): Rendered lines (as produced by :meth:`~rich.Console.render_lines`). + x (int, optional): x offset (column no). Defaults to 0. + y (int, optional): y offset (column no). Defaults to 0. + + Raises: + errors.NoAltScreen: If the Console isn't in alt screen mode. + """ + if not self.is_alt_screen: + raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") + screen_update = ScreenUpdate(lines, x, y) + segments = self.render(screen_update) + self._buffer.extend(segments) + self._check_buffer() + + def print_exception( + self, + *, + width: Optional[int] = 100, + extra_lines: int = 3, + theme: Optional[str] = None, + word_wrap: bool = False, + show_locals: bool = False, + suppress: Iterable[Union[str, ModuleType]] = (), + max_frames: int = 100, + ) -> None: + """Prints a rich render of the last exception and traceback. + + Args: + width (Optional[int], optional): Number of characters used to render code. Defaults to 100. + extra_lines (int, optional): Additional lines of code to render. Defaults to 3. + theme (str, optional): Override pygments theme used in traceback + word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + suppress (Iterable[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. + """ + from .traceback import Traceback + + traceback = Traceback( + width=width, + extra_lines=extra_lines, + theme=theme, + word_wrap=word_wrap, + show_locals=show_locals, + suppress=suppress, + max_frames=max_frames, + ) + self.print(traceback) + + @staticmethod + def _caller_frame_info( + offset: int, + currentframe: Callable[[], Optional[FrameType]] = inspect.currentframe, + ) -> Tuple[str, int, Dict[str, Any]]: + """Get caller frame information. + + Args: + offset (int): the caller offset within the current frame stack. + currentframe (Callable[[], Optional[FrameType]], optional): the callable to use to + retrieve the current frame. Defaults to ``inspect.currentframe``. + + Returns: + Tuple[str, int, Dict[str, Any]]: A tuple containing the filename, the line number and + the dictionary of local variables associated with the caller frame. + + Raises: + RuntimeError: If the stack offset is invalid. + """ + # Ignore the frame of this local helper + offset += 1 + + frame = currentframe() + if frame is not None: + # Use the faster currentframe where implemented + while offset and frame is not None: + frame = frame.f_back + offset -= 1 + assert frame is not None + return frame.f_code.co_filename, frame.f_lineno, frame.f_locals + else: + # Fallback to the slower stack + frame_info = inspect.stack()[offset] + return frame_info.filename, frame_info.lineno, frame_info.frame.f_locals + + def log( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + justify: Optional[JustifyMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + log_locals: bool = False, + _stack_offset: int = 1, + ) -> None: + """Log rich content to the terminal. + + Args: + objects (positional args): Objects to log to the terminal. + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to None. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to None. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to None. + log_locals (bool, optional): Boolean to enable logging of locals where ``log()`` + was called. Defaults to False. + _stack_offset (int, optional): Offset of caller from end of call stack. Defaults to 1. + """ + if not objects: + objects = (NewLine(),) + + render_hooks = self._render_hooks[:] + + with self: + renderables = self._collect_renderables( + objects, + sep, + end, + justify=justify, + emoji=emoji, + markup=markup, + highlight=highlight, + ) + if style is not None: + renderables = [Styled(renderable, style) for renderable in renderables] + + filename, line_no, locals = self._caller_frame_info(_stack_offset) + link_path = None if filename.startswith("<") else os.path.abspath(filename) + path = filename.rpartition(os.sep)[-1] + if log_locals: + locals_map = { + key: value + for key, value in locals.items() + if not key.startswith("__") + } + renderables.append(render_scope(locals_map, title="[i]locals")) + + renderables = [ + self._log_render( + self, + renderables, + log_time=self.get_datetime(), + path=path, + line_no=line_no, + link_path=link_path, + ) + ] + for hook in render_hooks: + renderables = hook.process_renderables(renderables) + new_segments: List[Segment] = [] + extend = new_segments.extend + render = self.render + render_options = self.options + for renderable in renderables: + extend(render(renderable, render_options)) + buffer_extend = self._buffer.extend + for line in Segment.split_and_crop_lines( + new_segments, self.width, pad=False + ): + buffer_extend(line) + + def _check_buffer(self) -> None: + """Check if the buffer may be rendered. Render it if it can (e.g. Console.quiet is False) + Rendering is supported on Windows, Unix and Jupyter environments. For + legacy Windows consoles, the win32 API is called directly. + This method will also record what it renders if recording is enabled via Console.record. + """ + if self.quiet: + del self._buffer[:] + return + with self._lock: + if self.record: + with self._record_buffer_lock: + self._record_buffer.extend(self._buffer[:]) + + if self._buffer_index == 0: + if self.is_jupyter: # pragma: no cover + from .jupyter import display + + display(self._buffer, self._render_buffer(self._buffer[:])) + del self._buffer[:] + else: + if WINDOWS: + use_legacy_windows_render = False + if self.legacy_windows: + fileno = get_fileno(self.file) + if fileno is not None: + use_legacy_windows_render = ( + fileno in _STD_STREAMS_OUTPUT + ) + + if use_legacy_windows_render: + from pip._vendor.rich._win32_console import LegacyWindowsTerm + from pip._vendor.rich._windows_renderer import legacy_windows_render + + buffer = self._buffer[:] + if self.no_color and self._color_system: + buffer = list(Segment.remove_color(buffer)) + + legacy_windows_render(buffer, LegacyWindowsTerm(self.file)) + else: + # Either a non-std stream on legacy Windows, or modern Windows. + text = self._render_buffer(self._buffer[:]) + # https://bugs.python.org/issue37871 + # https://github.com/python/cpython/issues/82052 + # We need to avoid writing more than 32Kb in a single write, due to the above bug + write = self.file.write + # Worse case scenario, every character is 4 bytes of utf-8 + MAX_WRITE = 32 * 1024 // 4 + try: + if len(text) <= MAX_WRITE: + write(text) + else: + batch: List[str] = [] + batch_append = batch.append + size = 0 + for line in text.splitlines(True): + if size + len(line) > MAX_WRITE and batch: + write("".join(batch)) + batch.clear() + size = 0 + batch_append(line) + size += len(line) + if batch: + write("".join(batch)) + batch.clear() + except UnicodeEncodeError as error: + error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" + raise + else: + text = self._render_buffer(self._buffer[:]) + try: + self.file.write(text) + except UnicodeEncodeError as error: + error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" + raise + + self.file.flush() + del self._buffer[:] + + def _render_buffer(self, buffer: Iterable[Segment]) -> str: + """Render buffered output, and clear buffer.""" + output: List[str] = [] + append = output.append + color_system = self._color_system + legacy_windows = self.legacy_windows + not_terminal = not self.is_terminal + if self.no_color and color_system: + buffer = Segment.remove_color(buffer) + for text, style, control in buffer: + if style: + append( + style.render( + text, + color_system=color_system, + legacy_windows=legacy_windows, + ) + ) + elif not (not_terminal and control): + append(text) + + rendered = "".join(output) + return rendered + + def input( + self, + prompt: TextType = "", + *, + markup: bool = True, + emoji: bool = True, + password: bool = False, + stream: Optional[TextIO] = None, + ) -> str: + """Displays a prompt and waits for input from the user. The prompt may contain color / style. + + It works in the same way as Python's builtin :func:`input` function and provides elaborate line editing and history features if Python's builtin :mod:`readline` module is previously loaded. + + Args: + prompt (Union[str, Text]): Text to render in the prompt. + markup (bool, optional): Enable console markup (requires a str prompt). Defaults to True. + emoji (bool, optional): Enable emoji (requires a str prompt). Defaults to True. + password: (bool, optional): Hide typed text. Defaults to False. + stream: (TextIO, optional): Optional file to read input from (rather than stdin). Defaults to None. + + Returns: + str: Text read from stdin. + """ + if prompt: + self.print(prompt, markup=markup, emoji=emoji, end="") + if password: + result = getpass("", stream=stream) + else: + if stream: + result = stream.readline() + else: + result = input() + return result + + def export_text(self, *, clear: bool = True, styles: bool = False) -> str: + """Generate text from console contents (requires record=True argument in constructor). + + Args: + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + styles (bool, optional): If ``True``, ansi escape codes will be included. ``False`` for plain text. + Defaults to ``False``. + + Returns: + str: String containing console contents. + + """ + assert ( + self.record + ), "To export console contents set record=True in the constructor or instance" + + with self._record_buffer_lock: + if styles: + text = "".join( + (style.render(text) if style else text) + for text, style, _ in self._record_buffer + ) + else: + text = "".join( + segment.text + for segment in self._record_buffer + if not segment.control + ) + if clear: + del self._record_buffer[:] + return text + + def save_text(self, path: str, *, clear: bool = True, styles: bool = False) -> None: + """Generate text from console and save to a given location (requires record=True argument in constructor). + + Args: + path (str): Path to write text files. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + styles (bool, optional): If ``True``, ansi style codes will be included. ``False`` for plain text. + Defaults to ``False``. + + """ + text = self.export_text(clear=clear, styles=styles) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(text) + + def export_html( + self, + *, + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: Optional[str] = None, + inline_styles: bool = False, + ) -> str: + """Generate HTML from console contents (requires record=True argument in constructor). + + Args: + theme (TerminalTheme, optional): TerminalTheme object containing console colors. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + code_format (str, optional): Format string to render HTML. In addition to '{foreground}', + '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. + inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files + larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. + Defaults to False. + + Returns: + str: String containing console contents as HTML. + """ + assert ( + self.record + ), "To export console contents set record=True in the constructor or instance" + fragments: List[str] = [] + append = fragments.append + _theme = theme or DEFAULT_TERMINAL_THEME + stylesheet = "" + + render_code_format = CONSOLE_HTML_FORMAT if code_format is None else code_format + + with self._record_buffer_lock: + if inline_styles: + for text, style, _ in Segment.filter_control( + Segment.simplify(self._record_buffer) + ): + text = escape(text) + if style: + rule = style.get_html_style(_theme) + if style.link: + text = f'
{text}' + text = f'{text}' if rule else text + append(text) + else: + styles: Dict[str, int] = {} + for text, style, _ in Segment.filter_control( + Segment.simplify(self._record_buffer) + ): + text = escape(text) + if style: + rule = style.get_html_style(_theme) + style_number = styles.setdefault(rule, len(styles) + 1) + if style.link: + text = f'{text}' + else: + text = f'{text}' + append(text) + stylesheet_rules: List[str] = [] + stylesheet_append = stylesheet_rules.append + for style_rule, style_number in styles.items(): + if style_rule: + stylesheet_append(f".r{style_number} {{{style_rule}}}") + stylesheet = "\n".join(stylesheet_rules) + + rendered_code = render_code_format.format( + code="".join(fragments), + stylesheet=stylesheet, + foreground=_theme.foreground_color.hex, + background=_theme.background_color.hex, + ) + if clear: + del self._record_buffer[:] + return rendered_code + + def save_html( + self, + path: str, + *, + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_HTML_FORMAT, + inline_styles: bool = False, + ) -> None: + """Generate HTML from console contents and write to a file (requires record=True argument in constructor). + + Args: + path (str): Path to write html file. + theme (TerminalTheme, optional): TerminalTheme object containing console colors. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + code_format (str, optional): Format string to render HTML. In addition to '{foreground}', + '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. + inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files + larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. + Defaults to False. + + """ + html = self.export_html( + theme=theme, + clear=clear, + code_format=code_format, + inline_styles=inline_styles, + ) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(html) + + def export_svg( + self, + *, + title: str = "Rich", + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_SVG_FORMAT, + font_aspect_ratio: float = 0.61, + unique_id: Optional[str] = None, + ) -> str: + """ + Generate an SVG from the console contents (requires record=True in Console constructor). + + Args: + title (str, optional): The title of the tab in the output image + theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` + code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables + into the string in order to form the final SVG output. The default template used and the variables + injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. + font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` + string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). + If you aren't specifying a different font inside ``code_format``, you probably don't need this. + unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node + ids). If not set, this defaults to a computed value based on the recorded content. + """ + + from pip._vendor.rich.cells import cell_len + + style_cache: Dict[Style, str] = {} + + def get_svg_style(style: Style) -> str: + """Convert a Style to CSS rules for SVG.""" + if style in style_cache: + return style_cache[style] + css_rules = [] + color = ( + _theme.foreground_color + if (style.color is None or style.color.is_default) + else style.color.get_truecolor(_theme) + ) + bgcolor = ( + _theme.background_color + if (style.bgcolor is None or style.bgcolor.is_default) + else style.bgcolor.get_truecolor(_theme) + ) + if style.reverse: + color, bgcolor = bgcolor, color + if style.dim: + color = blend_rgb(color, bgcolor, 0.4) + css_rules.append(f"fill: {color.hex}") + if style.bold: + css_rules.append("font-weight: bold") + if style.italic: + css_rules.append("font-style: italic;") + if style.underline: + css_rules.append("text-decoration: underline;") + if style.strike: + css_rules.append("text-decoration: line-through;") + + css = ";".join(css_rules) + style_cache[style] = css + return css + + _theme = theme or SVG_EXPORT_THEME + + width = self.width + char_height = 20 + char_width = char_height * font_aspect_ratio + line_height = char_height * 1.22 + + margin_top = 1 + margin_right = 1 + margin_bottom = 1 + margin_left = 1 + + padding_top = 40 + padding_right = 8 + padding_bottom = 8 + padding_left = 8 + + padding_width = padding_left + padding_right + padding_height = padding_top + padding_bottom + margin_width = margin_left + margin_right + margin_height = margin_top + margin_bottom + + text_backgrounds: List[str] = [] + text_group: List[str] = [] + classes: Dict[str, int] = {} + style_no = 1 + + def escape_text(text: str) -> str: + """HTML escape text and replace spaces with nbsp.""" + return escape(text).replace(" ", " ") + + def make_tag( + name: str, content: Optional[str] = None, **attribs: object + ) -> str: + """Make a tag from name, content, and attributes.""" + + def stringify(value: object) -> str: + if isinstance(value, (float)): + return format(value, "g") + return str(value) + + tag_attribs = " ".join( + f'{k.lstrip("_").replace("_", "-")}="{stringify(v)}"' + for k, v in attribs.items() + ) + return ( + f"<{name} {tag_attribs}>{content}" + if content + else f"<{name} {tag_attribs}/>" + ) + + with self._record_buffer_lock: + segments = list(Segment.filter_control(self._record_buffer)) + if clear: + self._record_buffer.clear() + + if unique_id is None: + unique_id = "terminal-" + str( + zlib.adler32( + ("".join(repr(segment) for segment in segments)).encode( + "utf-8", + "ignore", + ) + + title.encode("utf-8", "ignore") + ) + ) + y = 0 + for y, line in enumerate(Segment.split_and_crop_lines(segments, length=width)): + x = 0 + for text, style, _control in line: + style = style or Style() + rules = get_svg_style(style) + if rules not in classes: + classes[rules] = style_no + style_no += 1 + class_name = f"r{classes[rules]}" + + if style.reverse: + has_background = True + background = ( + _theme.foreground_color.hex + if style.color is None + else style.color.get_truecolor(_theme).hex + ) + else: + bgcolor = style.bgcolor + has_background = bgcolor is not None and not bgcolor.is_default + background = ( + _theme.background_color.hex + if style.bgcolor is None + else style.bgcolor.get_truecolor(_theme).hex + ) + + text_length = cell_len(text) + if has_background: + text_backgrounds.append( + make_tag( + "rect", + fill=background, + x=x * char_width, + y=y * line_height + 1.5, + width=char_width * text_length, + height=line_height + 0.25, + shape_rendering="crispEdges", + ) + ) + + if text != " " * len(text): + text_group.append( + make_tag( + "text", + escape_text(text), + _class=f"{unique_id}-{class_name}", + x=x * char_width, + y=y * line_height + char_height, + textLength=char_width * len(text), + clip_path=f"url(#{unique_id}-line-{y})", + ) + ) + x += cell_len(text) + + line_offsets = [line_no * line_height + 1.5 for line_no in range(y)] + lines = "\n".join( + f""" + {make_tag("rect", x=0, y=offset, width=char_width * width, height=line_height + 0.25)} + """ + for line_no, offset in enumerate(line_offsets) + ) + + styles = "\n".join( + f".{unique_id}-r{rule_no} {{ {css} }}" for css, rule_no in classes.items() + ) + backgrounds = "".join(text_backgrounds) + matrix = "".join(text_group) + + terminal_width = ceil(width * char_width + padding_width) + terminal_height = (y + 1) * line_height + padding_height + chrome = make_tag( + "rect", + fill=_theme.background_color.hex, + stroke="rgba(255,255,255,0.35)", + stroke_width="1", + x=margin_left, + y=margin_top, + width=terminal_width, + height=terminal_height, + rx=8, + ) + + title_color = _theme.foreground_color.hex + if title: + chrome += make_tag( + "text", + escape_text(title), + _class=f"{unique_id}-title", + fill=title_color, + text_anchor="middle", + x=terminal_width // 2, + y=margin_top + char_height + 6, + ) + chrome += f""" + + + + + + """ + + svg = code_format.format( + unique_id=unique_id, + char_width=char_width, + char_height=char_height, + line_height=line_height, + terminal_width=char_width * width - 1, + terminal_height=(y + 1) * line_height - 1, + width=terminal_width + margin_width, + height=terminal_height + margin_height, + terminal_x=margin_left + padding_left, + terminal_y=margin_top + padding_top, + styles=styles, + chrome=chrome, + backgrounds=backgrounds, + matrix=matrix, + lines=lines, + ) + return svg + + def save_svg( + self, + path: str, + *, + title: str = "Rich", + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_SVG_FORMAT, + font_aspect_ratio: float = 0.61, + unique_id: Optional[str] = None, + ) -> None: + """Generate an SVG file from the console contents (requires record=True in Console constructor). + + Args: + path (str): The path to write the SVG to. + title (str, optional): The title of the tab in the output image + theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` + code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables + into the string in order to form the final SVG output. The default template used and the variables + injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. + font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` + string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). + If you aren't specifying a different font inside ``code_format``, you probably don't need this. + unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node + ids). If not set, this defaults to a computed value based on the recorded content. + """ + svg = self.export_svg( + title=title, + theme=theme, + clear=clear, + code_format=code_format, + font_aspect_ratio=font_aspect_ratio, + unique_id=unique_id, + ) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(svg) + + +def _svg_hash(svg_main_code: str) -> str: + """Returns a unique hash for the given SVG main code. + + Args: + svg_main_code (str): The content we're going to inject in the SVG envelope. + + Returns: + str: a hash of the given content + """ + return str(zlib.adler32(svg_main_code.encode())) + + +if __name__ == "__main__": # pragma: no cover + console = Console(record=True) + + console.log( + "JSONRPC [i]request[/i]", + 5, + 1.3, + True, + False, + None, + { + "jsonrpc": "2.0", + "method": "subtract", + "params": {"minuend": 42, "subtrahend": 23}, + "id": 3, + }, + ) + + console.log("Hello, World!", "{'a': 1}", repr(console)) + + console.print( + { + "name": None, + "empty": [], + "quiz": { + "sport": { + "answered": True, + "q1": { + "question": "Which one is correct team name in NBA?", + "options": [ + "New York Bulls", + "Los Angeles Kings", + "Golden State Warriors", + "Huston Rocket", + ], + "answer": "Huston Rocket", + }, + }, + "maths": { + "answered": False, + "q1": { + "question": "5 + 7 = ?", + "options": [10, 11, 12, 13], + "answer": 12, + }, + "q2": { + "question": "12 - 8 = ?", + "options": [1, 2, 3, 4], + "answer": 4, + }, + }, + }, + } + ) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/constrain.py b/venv/Lib/site-packages/pip/_vendor/rich/constrain.py new file mode 100644 index 0000000..65fdf56 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/constrain.py @@ -0,0 +1,37 @@ +from typing import Optional, TYPE_CHECKING + +from .jupyter import JupyterMixin +from .measure import Measurement + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType, RenderResult + + +class Constrain(JupyterMixin): + """Constrain the width of a renderable to a given number of characters. + + Args: + renderable (RenderableType): A renderable object. + width (int, optional): The maximum width (in characters) to render. Defaults to 80. + """ + + def __init__(self, renderable: "RenderableType", width: Optional[int] = 80) -> None: + self.renderable = renderable + self.width = width + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.width is None: + yield self.renderable + else: + child_options = options.update_width(min(self.width, options.max_width)) + yield from console.render(self.renderable, child_options) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + if self.width is not None: + options = options.update_width(self.width) + measurement = Measurement.get(console, options, self.renderable) + return measurement diff --git a/venv/Lib/site-packages/pip/_vendor/rich/containers.py b/venv/Lib/site-packages/pip/_vendor/rich/containers.py new file mode 100644 index 0000000..901ff8b --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/containers.py @@ -0,0 +1,167 @@ +from itertools import zip_longest +from typing import ( + TYPE_CHECKING, + Iterable, + Iterator, + List, + Optional, + TypeVar, + Union, + overload, +) + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + JustifyMethod, + OverflowMethod, + RenderResult, + RenderableType, + ) + from .text import Text + +from .cells import cell_len +from .measure import Measurement + +T = TypeVar("T") + + +class Renderables: + """A list subclass which renders its contents to the console.""" + + def __init__( + self, renderables: Optional[Iterable["RenderableType"]] = None + ) -> None: + self._renderables: List["RenderableType"] = ( + list(renderables) if renderables is not None else [] + ) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + """Console render method to insert line-breaks.""" + yield from self._renderables + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + dimensions = [ + Measurement.get(console, options, renderable) + for renderable in self._renderables + ] + if not dimensions: + return Measurement(1, 1) + _min = max(dimension.minimum for dimension in dimensions) + _max = max(dimension.maximum for dimension in dimensions) + return Measurement(_min, _max) + + def append(self, renderable: "RenderableType") -> None: + self._renderables.append(renderable) + + def __iter__(self) -> Iterable["RenderableType"]: + return iter(self._renderables) + + +class Lines: + """A list subclass which can render to the console.""" + + def __init__(self, lines: Iterable["Text"] = ()) -> None: + self._lines: List["Text"] = list(lines) + + def __repr__(self) -> str: + return f"Lines({self._lines!r})" + + def __iter__(self) -> Iterator["Text"]: + return iter(self._lines) + + @overload + def __getitem__(self, index: int) -> "Text": + ... + + @overload + def __getitem__(self, index: slice) -> List["Text"]: + ... + + def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]: + return self._lines[index] + + def __setitem__(self, index: int, value: "Text") -> "Lines": + self._lines[index] = value + return self + + def __len__(self) -> int: + return self._lines.__len__() + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + """Console render method to insert line-breaks.""" + yield from self._lines + + def append(self, line: "Text") -> None: + self._lines.append(line) + + def extend(self, lines: Iterable["Text"]) -> None: + self._lines.extend(lines) + + def pop(self, index: int = -1) -> "Text": + return self._lines.pop(index) + + def justify( + self, + console: "Console", + width: int, + justify: "JustifyMethod" = "left", + overflow: "OverflowMethod" = "fold", + ) -> None: + """Justify and overflow text to a given width. + + Args: + console (Console): Console instance. + width (int): Number of cells available per line. + justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left". + overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold". + + """ + from .text import Text + + if justify == "left": + for line in self._lines: + line.truncate(width, overflow=overflow, pad=True) + elif justify == "center": + for line in self._lines: + line.rstrip() + line.truncate(width, overflow=overflow) + line.pad_left((width - cell_len(line.plain)) // 2) + line.pad_right(width - cell_len(line.plain)) + elif justify == "right": + for line in self._lines: + line.rstrip() + line.truncate(width, overflow=overflow) + line.pad_left(width - cell_len(line.plain)) + elif justify == "full": + for line_index, line in enumerate(self._lines): + if line_index == len(self._lines) - 1: + break + words = line.split(" ") + words_size = sum(cell_len(word.plain) for word in words) + num_spaces = len(words) - 1 + spaces = [1 for _ in range(num_spaces)] + index = 0 + if spaces: + while words_size + num_spaces < width: + spaces[len(spaces) - index - 1] += 1 + num_spaces += 1 + index = (index + 1) % len(spaces) + tokens: List[Text] = [] + for index, (word, next_word) in enumerate( + zip_longest(words, words[1:]) + ): + tokens.append(word) + if index < len(spaces): + style = word.get_style_at_offset(console, -1) + next_style = next_word.get_style_at_offset(console, 0) + space_style = style if style == next_style else line.style + tokens.append(Text(" " * spaces[index], style=space_style)) + self[line_index] = Text("").join(tokens) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/control.py b/venv/Lib/site-packages/pip/_vendor/rich/control.py new file mode 100644 index 0000000..88fcb92 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/control.py @@ -0,0 +1,225 @@ +import sys +import time +from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union + +if sys.version_info >= (3, 8): + from typing import Final +else: + from pip._vendor.typing_extensions import Final # pragma: no cover + +from .segment import ControlCode, ControlType, Segment + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult + +STRIP_CONTROL_CODES: Final = [ + 7, # Bell + 8, # Backspace + 11, # Vertical tab + 12, # Form feed + 13, # Carriage return +] +_CONTROL_STRIP_TRANSLATE: Final = { + _codepoint: None for _codepoint in STRIP_CONTROL_CODES +} + +CONTROL_ESCAPE: Final = { + 7: "\\a", + 8: "\\b", + 11: "\\v", + 12: "\\f", + 13: "\\r", +} + +CONTROL_CODES_FORMAT: Dict[int, Callable[..., str]] = { + ControlType.BELL: lambda: "\x07", + ControlType.CARRIAGE_RETURN: lambda: "\r", + ControlType.HOME: lambda: "\x1b[H", + ControlType.CLEAR: lambda: "\x1b[2J", + ControlType.ENABLE_ALT_SCREEN: lambda: "\x1b[?1049h", + ControlType.DISABLE_ALT_SCREEN: lambda: "\x1b[?1049l", + ControlType.SHOW_CURSOR: lambda: "\x1b[?25h", + ControlType.HIDE_CURSOR: lambda: "\x1b[?25l", + ControlType.CURSOR_UP: lambda param: f"\x1b[{param}A", + ControlType.CURSOR_DOWN: lambda param: f"\x1b[{param}B", + ControlType.CURSOR_FORWARD: lambda param: f"\x1b[{param}C", + ControlType.CURSOR_BACKWARD: lambda param: f"\x1b[{param}D", + ControlType.CURSOR_MOVE_TO_COLUMN: lambda param: f"\x1b[{param+1}G", + ControlType.ERASE_IN_LINE: lambda param: f"\x1b[{param}K", + ControlType.CURSOR_MOVE_TO: lambda x, y: f"\x1b[{y+1};{x+1}H", + ControlType.SET_WINDOW_TITLE: lambda title: f"\x1b]0;{title}\x07", +} + + +class Control: + """A renderable that inserts a control code (non printable but may move cursor). + + Args: + *codes (str): Positional arguments are either a :class:`~rich.segment.ControlType` enum or a + tuple of ControlType and an integer parameter + """ + + __slots__ = ["segment"] + + def __init__(self, *codes: Union[ControlType, ControlCode]) -> None: + control_codes: List[ControlCode] = [ + (code,) if isinstance(code, ControlType) else code for code in codes + ] + _format_map = CONTROL_CODES_FORMAT + rendered_codes = "".join( + _format_map[code](*parameters) for code, *parameters in control_codes + ) + self.segment = Segment(rendered_codes, None, control_codes) + + @classmethod + def bell(cls) -> "Control": + """Ring the 'bell'.""" + return cls(ControlType.BELL) + + @classmethod + def home(cls) -> "Control": + """Move cursor to 'home' position.""" + return cls(ControlType.HOME) + + @classmethod + def move(cls, x: int = 0, y: int = 0) -> "Control": + """Move cursor relative to current position. + + Args: + x (int): X offset. + y (int): Y offset. + + Returns: + ~Control: Control object. + + """ + + def get_codes() -> Iterable[ControlCode]: + control = ControlType + if x: + yield ( + control.CURSOR_FORWARD if x > 0 else control.CURSOR_BACKWARD, + abs(x), + ) + if y: + yield ( + control.CURSOR_DOWN if y > 0 else control.CURSOR_UP, + abs(y), + ) + + control = cls(*get_codes()) + return control + + @classmethod + def move_to_column(cls, x: int, y: int = 0) -> "Control": + """Move to the given column, optionally add offset to row. + + Returns: + x (int): absolute x (column) + y (int): optional y offset (row) + + Returns: + ~Control: Control object. + """ + + return ( + cls( + (ControlType.CURSOR_MOVE_TO_COLUMN, x), + ( + ControlType.CURSOR_DOWN if y > 0 else ControlType.CURSOR_UP, + abs(y), + ), + ) + if y + else cls((ControlType.CURSOR_MOVE_TO_COLUMN, x)) + ) + + @classmethod + def move_to(cls, x: int, y: int) -> "Control": + """Move cursor to absolute position. + + Args: + x (int): x offset (column) + y (int): y offset (row) + + Returns: + ~Control: Control object. + """ + return cls((ControlType.CURSOR_MOVE_TO, x, y)) + + @classmethod + def clear(cls) -> "Control": + """Clear the screen.""" + return cls(ControlType.CLEAR) + + @classmethod + def show_cursor(cls, show: bool) -> "Control": + """Show or hide the cursor.""" + return cls(ControlType.SHOW_CURSOR if show else ControlType.HIDE_CURSOR) + + @classmethod + def alt_screen(cls, enable: bool) -> "Control": + """Enable or disable alt screen.""" + if enable: + return cls(ControlType.ENABLE_ALT_SCREEN, ControlType.HOME) + else: + return cls(ControlType.DISABLE_ALT_SCREEN) + + @classmethod + def title(cls, title: str) -> "Control": + """Set the terminal window title + + Args: + title (str): The new terminal window title + """ + return cls((ControlType.SET_WINDOW_TITLE, title)) + + def __str__(self) -> str: + return self.segment.text + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.segment.text: + yield self.segment + + +def strip_control_codes( + text: str, _translate_table: Dict[int, None] = _CONTROL_STRIP_TRANSLATE +) -> str: + """Remove control codes from text. + + Args: + text (str): A string possibly contain control codes. + + Returns: + str: String with control codes removed. + """ + return text.translate(_translate_table) + + +def escape_control_codes( + text: str, + _translate_table: Dict[int, str] = CONTROL_ESCAPE, +) -> str: + """Replace control codes with their "escaped" equivalent in the given text. + (e.g. "\b" becomes "\\b") + + Args: + text (str): A string possibly containing control codes. + + Returns: + str: String with control codes replaced with their escaped version. + """ + return text.translate(_translate_table) + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + + console = Console() + console.print("Look at the title of your terminal window ^") + # console.print(Control((ControlType.SET_WINDOW_TITLE, "Hello, world!"))) + for i in range(10): + console.set_window_title("🚀 Loading" + "." * i) + time.sleep(0.5) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/default_styles.py b/venv/Lib/site-packages/pip/_vendor/rich/default_styles.py new file mode 100644 index 0000000..dca3719 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/default_styles.py @@ -0,0 +1,190 @@ +from typing import Dict + +from .style import Style + +DEFAULT_STYLES: Dict[str, Style] = { + "none": Style.null(), + "reset": Style( + color="default", + bgcolor="default", + dim=False, + bold=False, + italic=False, + underline=False, + blink=False, + blink2=False, + reverse=False, + conceal=False, + strike=False, + ), + "dim": Style(dim=True), + "bright": Style(dim=False), + "bold": Style(bold=True), + "strong": Style(bold=True), + "code": Style(reverse=True, bold=True), + "italic": Style(italic=True), + "emphasize": Style(italic=True), + "underline": Style(underline=True), + "blink": Style(blink=True), + "blink2": Style(blink2=True), + "reverse": Style(reverse=True), + "strike": Style(strike=True), + "black": Style(color="black"), + "red": Style(color="red"), + "green": Style(color="green"), + "yellow": Style(color="yellow"), + "magenta": Style(color="magenta"), + "cyan": Style(color="cyan"), + "white": Style(color="white"), + "inspect.attr": Style(color="yellow", italic=True), + "inspect.attr.dunder": Style(color="yellow", italic=True, dim=True), + "inspect.callable": Style(bold=True, color="red"), + "inspect.async_def": Style(italic=True, color="bright_cyan"), + "inspect.def": Style(italic=True, color="bright_cyan"), + "inspect.class": Style(italic=True, color="bright_cyan"), + "inspect.error": Style(bold=True, color="red"), + "inspect.equals": Style(), + "inspect.help": Style(color="cyan"), + "inspect.doc": Style(dim=True), + "inspect.value.border": Style(color="green"), + "live.ellipsis": Style(bold=True, color="red"), + "layout.tree.row": Style(dim=False, color="red"), + "layout.tree.column": Style(dim=False, color="blue"), + "logging.keyword": Style(bold=True, color="yellow"), + "logging.level.notset": Style(dim=True), + "logging.level.debug": Style(color="green"), + "logging.level.info": Style(color="blue"), + "logging.level.warning": Style(color="red"), + "logging.level.error": Style(color="red", bold=True), + "logging.level.critical": Style(color="red", bold=True, reverse=True), + "log.level": Style.null(), + "log.time": Style(color="cyan", dim=True), + "log.message": Style.null(), + "log.path": Style(dim=True), + "repr.ellipsis": Style(color="yellow"), + "repr.indent": Style(color="green", dim=True), + "repr.error": Style(color="red", bold=True), + "repr.str": Style(color="green", italic=False, bold=False), + "repr.brace": Style(bold=True), + "repr.comma": Style(bold=True), + "repr.ipv4": Style(bold=True, color="bright_green"), + "repr.ipv6": Style(bold=True, color="bright_green"), + "repr.eui48": Style(bold=True, color="bright_green"), + "repr.eui64": Style(bold=True, color="bright_green"), + "repr.tag_start": Style(bold=True), + "repr.tag_name": Style(color="bright_magenta", bold=True), + "repr.tag_contents": Style(color="default"), + "repr.tag_end": Style(bold=True), + "repr.attrib_name": Style(color="yellow", italic=False), + "repr.attrib_equal": Style(bold=True), + "repr.attrib_value": Style(color="magenta", italic=False), + "repr.number": Style(color="cyan", bold=True, italic=False), + "repr.number_complex": Style(color="cyan", bold=True, italic=False), # same + "repr.bool_true": Style(color="bright_green", italic=True), + "repr.bool_false": Style(color="bright_red", italic=True), + "repr.none": Style(color="magenta", italic=True), + "repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False), + "repr.uuid": Style(color="bright_yellow", bold=False), + "repr.call": Style(color="magenta", bold=True), + "repr.path": Style(color="magenta"), + "repr.filename": Style(color="bright_magenta"), + "rule.line": Style(color="bright_green"), + "rule.text": Style.null(), + "json.brace": Style(bold=True), + "json.bool_true": Style(color="bright_green", italic=True), + "json.bool_false": Style(color="bright_red", italic=True), + "json.null": Style(color="magenta", italic=True), + "json.number": Style(color="cyan", bold=True, italic=False), + "json.str": Style(color="green", italic=False, bold=False), + "json.key": Style(color="blue", bold=True), + "prompt": Style.null(), + "prompt.choices": Style(color="magenta", bold=True), + "prompt.default": Style(color="cyan", bold=True), + "prompt.invalid": Style(color="red"), + "prompt.invalid.choice": Style(color="red"), + "pretty": Style.null(), + "scope.border": Style(color="blue"), + "scope.key": Style(color="yellow", italic=True), + "scope.key.special": Style(color="yellow", italic=True, dim=True), + "scope.equals": Style(color="red"), + "table.header": Style(bold=True), + "table.footer": Style(bold=True), + "table.cell": Style.null(), + "table.title": Style(italic=True), + "table.caption": Style(italic=True, dim=True), + "traceback.error": Style(color="red", italic=True), + "traceback.border.syntax_error": Style(color="bright_red"), + "traceback.border": Style(color="red"), + "traceback.text": Style.null(), + "traceback.title": Style(color="red", bold=True), + "traceback.exc_type": Style(color="bright_red", bold=True), + "traceback.exc_value": Style.null(), + "traceback.offset": Style(color="bright_red", bold=True), + "bar.back": Style(color="grey23"), + "bar.complete": Style(color="rgb(249,38,114)"), + "bar.finished": Style(color="rgb(114,156,31)"), + "bar.pulse": Style(color="rgb(249,38,114)"), + "progress.description": Style.null(), + "progress.filesize": Style(color="green"), + "progress.filesize.total": Style(color="green"), + "progress.download": Style(color="green"), + "progress.elapsed": Style(color="yellow"), + "progress.percentage": Style(color="magenta"), + "progress.remaining": Style(color="cyan"), + "progress.data.speed": Style(color="red"), + "progress.spinner": Style(color="green"), + "status.spinner": Style(color="green"), + "tree": Style(), + "tree.line": Style(), + "markdown.paragraph": Style(), + "markdown.text": Style(), + "markdown.em": Style(italic=True), + "markdown.emph": Style(italic=True), # For commonmark backwards compatibility + "markdown.strong": Style(bold=True), + "markdown.code": Style(bold=True, color="cyan", bgcolor="black"), + "markdown.code_block": Style(color="cyan", bgcolor="black"), + "markdown.block_quote": Style(color="magenta"), + "markdown.list": Style(color="cyan"), + "markdown.item": Style(), + "markdown.item.bullet": Style(color="yellow", bold=True), + "markdown.item.number": Style(color="yellow", bold=True), + "markdown.hr": Style(color="yellow"), + "markdown.h1.border": Style(), + "markdown.h1": Style(bold=True), + "markdown.h2": Style(bold=True, underline=True), + "markdown.h3": Style(bold=True), + "markdown.h4": Style(bold=True, dim=True), + "markdown.h5": Style(underline=True), + "markdown.h6": Style(italic=True), + "markdown.h7": Style(italic=True, dim=True), + "markdown.link": Style(color="bright_blue"), + "markdown.link_url": Style(color="blue", underline=True), + "markdown.s": Style(strike=True), + "iso8601.date": Style(color="blue"), + "iso8601.time": Style(color="magenta"), + "iso8601.timezone": Style(color="yellow"), +} + + +if __name__ == "__main__": # pragma: no cover + import argparse + import io + + from pip._vendor.rich.console import Console + from pip._vendor.rich.table import Table + from pip._vendor.rich.text import Text + + parser = argparse.ArgumentParser() + parser.add_argument("--html", action="store_true", help="Export as HTML table") + args = parser.parse_args() + html: bool = args.html + console = Console(record=True, width=70, file=io.StringIO()) if html else Console() + + table = Table("Name", "Styling") + + for style_name, style in DEFAULT_STYLES.items(): + table.add_row(Text(style_name, style=style), str(style)) + + console.print(table) + if html: + print(console.export_html(inline_styles=True)) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/diagnose.py b/venv/Lib/site-packages/pip/_vendor/rich/diagnose.py new file mode 100644 index 0000000..ad36183 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/diagnose.py @@ -0,0 +1,37 @@ +import os +import platform + +from pip._vendor.rich import inspect +from pip._vendor.rich.console import Console, get_windows_console_features +from pip._vendor.rich.panel import Panel +from pip._vendor.rich.pretty import Pretty + + +def report() -> None: # pragma: no cover + """Print a report to the terminal with debugging information""" + console = Console() + inspect(console) + features = get_windows_console_features() + inspect(features) + + env_names = ( + "TERM", + "COLORTERM", + "CLICOLOR", + "NO_COLOR", + "TERM_PROGRAM", + "COLUMNS", + "LINES", + "JUPYTER_COLUMNS", + "JUPYTER_LINES", + "JPY_PARENT_PID", + "VSCODE_VERBOSE_LOGGING", + ) + env = {name: os.getenv(name) for name in env_names} + console.print(Panel.fit((Pretty(env)), title="[b]Environment Variables")) + + console.print(f'platform="{platform.system()}"') + + +if __name__ == "__main__": # pragma: no cover + report() diff --git a/venv/Lib/site-packages/pip/_vendor/rich/emoji.py b/venv/Lib/site-packages/pip/_vendor/rich/emoji.py new file mode 100644 index 0000000..791f046 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/emoji.py @@ -0,0 +1,96 @@ +import sys +from typing import TYPE_CHECKING, Optional, Union + +from .jupyter import JupyterMixin +from .segment import Segment +from .style import Style +from ._emoji_codes import EMOJI +from ._emoji_replace import _emoji_replace + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult + + +EmojiVariant = Literal["emoji", "text"] + + +class NoEmoji(Exception): + """No emoji by that name.""" + + +class Emoji(JupyterMixin): + __slots__ = ["name", "style", "_char", "variant"] + + VARIANTS = {"text": "\uFE0E", "emoji": "\uFE0F"} + + def __init__( + self, + name: str, + style: Union[str, Style] = "none", + variant: Optional[EmojiVariant] = None, + ) -> None: + """A single emoji character. + + Args: + name (str): Name of emoji. + style (Union[str, Style], optional): Optional style. Defaults to None. + + Raises: + NoEmoji: If the emoji doesn't exist. + """ + self.name = name + self.style = style + self.variant = variant + try: + self._char = EMOJI[name] + except KeyError: + raise NoEmoji(f"No emoji called {name!r}") + if variant is not None: + self._char += self.VARIANTS.get(variant, "") + + @classmethod + def replace(cls, text: str) -> str: + """Replace emoji markup with corresponding unicode characters. + + Args: + text (str): A string with emojis codes, e.g. "Hello :smiley:!" + + Returns: + str: A string with emoji codes replaces with actual emoji. + """ + return _emoji_replace(text) + + def __repr__(self) -> str: + return f"" + + def __str__(self) -> str: + return self._char + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + yield Segment(self._char, console.get_style(self.style)) + + +if __name__ == "__main__": # pragma: no cover + import sys + + from pip._vendor.rich.columns import Columns + from pip._vendor.rich.console import Console + + console = Console(record=True) + + columns = Columns( + (f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name), + column_first=True, + ) + + console.print(columns) + if len(sys.argv) > 1: + console.save_html(sys.argv[1]) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/errors.py b/venv/Lib/site-packages/pip/_vendor/rich/errors.py new file mode 100644 index 0000000..0bcbe53 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/errors.py @@ -0,0 +1,34 @@ +class ConsoleError(Exception): + """An error in console operation.""" + + +class StyleError(Exception): + """An error in styles.""" + + +class StyleSyntaxError(ConsoleError): + """Style was badly formatted.""" + + +class MissingStyle(StyleError): + """No such style.""" + + +class StyleStackError(ConsoleError): + """Style stack is invalid.""" + + +class NotRenderableError(ConsoleError): + """Object is not renderable.""" + + +class MarkupError(ConsoleError): + """Markup was badly formatted.""" + + +class LiveError(ConsoleError): + """Error related to Live display.""" + + +class NoAltScreen(ConsoleError): + """Alt screen mode was required.""" diff --git a/venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py b/venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py new file mode 100644 index 0000000..4b0b0da --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py @@ -0,0 +1,57 @@ +import io +from typing import IO, TYPE_CHECKING, Any, List + +from .ansi import AnsiDecoder +from .text import Text + +if TYPE_CHECKING: + from .console import Console + + +class FileProxy(io.TextIOBase): + """Wraps a file (e.g. sys.stdout) and redirects writes to a console.""" + + def __init__(self, console: "Console", file: IO[str]) -> None: + self.__console = console + self.__file = file + self.__buffer: List[str] = [] + self.__ansi_decoder = AnsiDecoder() + + @property + def rich_proxied_file(self) -> IO[str]: + """Get proxied file.""" + return self.__file + + def __getattr__(self, name: str) -> Any: + return getattr(self.__file, name) + + def write(self, text: str) -> int: + if not isinstance(text, str): + raise TypeError(f"write() argument must be str, not {type(text).__name__}") + buffer = self.__buffer + lines: List[str] = [] + while text: + line, new_line, text = text.partition("\n") + if new_line: + lines.append("".join(buffer) + line) + buffer.clear() + else: + buffer.append(line) + break + if lines: + console = self.__console + with console: + output = Text("\n").join( + self.__ansi_decoder.decode_line(line) for line in lines + ) + console.print(output) + return len(text) + + def flush(self) -> None: + output = "".join(self.__buffer) + if output: + self.__console.print(output) + del self.__buffer[:] + + def fileno(self) -> int: + return self.__file.fileno() diff --git a/venv/Lib/site-packages/pip/_vendor/rich/filesize.py b/venv/Lib/site-packages/pip/_vendor/rich/filesize.py new file mode 100644 index 0000000..99f118e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/filesize.py @@ -0,0 +1,89 @@ +# coding: utf-8 +"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2 + +The functions declared in this module should cover the different +use cases needed to generate a string representation of a file size +using several different units. Since there are many standards regarding +file size units, three different functions have been implemented. + +See Also: + * `Wikipedia: Binary prefix `_ + +""" + +__all__ = ["decimal"] + +from typing import Iterable, List, Optional, Tuple + + +def _to_str( + size: int, + suffixes: Iterable[str], + base: int, + *, + precision: Optional[int] = 1, + separator: Optional[str] = " ", +) -> str: + if size == 1: + return "1 byte" + elif size < base: + return "{:,} bytes".format(size) + + for i, suffix in enumerate(suffixes, 2): # noqa: B007 + unit = base**i + if size < unit: + break + return "{:,.{precision}f}{separator}{}".format( + (base * size / unit), + suffix, + precision=precision, + separator=separator, + ) + + +def pick_unit_and_suffix(size: int, suffixes: List[str], base: int) -> Tuple[int, str]: + """Pick a suffix and base for the given size.""" + for i, suffix in enumerate(suffixes): + unit = base**i + if size < unit * base: + break + return unit, suffix + + +def decimal( + size: int, + *, + precision: Optional[int] = 1, + separator: Optional[str] = " ", +) -> str: + """Convert a filesize in to a string (powers of 1000, SI prefixes). + + In this convention, ``1000 B = 1 kB``. + + This is typically the format used to advertise the storage + capacity of USB flash drives and the like (*256 MB* meaning + actually a storage capacity of more than *256 000 000 B*), + or used by **Mac OS X** since v10.6 to report file sizes. + + Arguments: + int (size): A file size. + int (precision): The number of decimal places to include (default = 1). + str (separator): The string to separate the value from the units (default = " "). + + Returns: + `str`: A string containing a abbreviated file size and units. + + Example: + >>> filesize.decimal(30000) + '30.0 kB' + >>> filesize.decimal(30000, precision=2, separator="") + '30.00kB' + + """ + return _to_str( + size, + ("kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"), + 1000, + precision=precision, + separator=separator, + ) diff --git a/venv/Lib/site-packages/pip/_vendor/rich/highlighter.py b/venv/Lib/site-packages/pip/_vendor/rich/highlighter.py new file mode 100644 index 0000000..27714b2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/rich/highlighter.py @@ -0,0 +1,232 @@ +import re +from abc import ABC, abstractmethod +from typing import List, Union + +from .text import Span, Text + + +def _combine_regex(*regexes: str) -> str: + """Combine a number of regexes in to a single regex. + + Returns: + str: New regex with all regexes ORed together. + """ + return "|".join(regexes) + + +class Highlighter(ABC): + """Abstract base class for highlighters.""" + + def __call__(self, text: Union[str, Text]) -> Text: + """Highlight a str or Text instance. + + Args: + text (Union[str, ~Text]): Text to highlight. + + Raises: + TypeError: If not called with text or str. + + Returns: + Text: A test instance with highlighting applied. + """ + if isinstance(text, str): + highlight_text = Text(text) + elif isinstance(text, Text): + highlight_text = text.copy() + else: + raise TypeError(f"str or Text instance required, not {text!r}") + self.highlight(highlight_text) + return highlight_text + + @abstractmethod + def highlight(self, text: Text) -> None: + """Apply highlighting in place to text. + + Args: + text (~Text): A text object highlight. + """ + + +class NullHighlighter(Highlighter): + """A highlighter object that doesn't highlight. + + May be used to disable highlighting entirely. + + """ + + def highlight(self, text: Text) -> None: + """Nothing to do""" + + +class RegexHighlighter(Highlighter): + """Applies highlighting from a list of regular expressions.""" + + highlights: List[str] = [] + base_style: str = "" + + def highlight(self, text: Text) -> None: + """Highlight :class:`rich.text.Text` using regular expressions. + + Args: + text (~Text): Text to highlighted. + + """ + + highlight_regex = text.highlight_regex + for re_highlight in self.highlights: + highlight_regex(re_highlight, style_prefix=self.base_style) + + +class ReprHighlighter(RegexHighlighter): + """Highlights the text typically produced from ``__repr__`` methods.""" + + base_style = "repr." + highlights = [ + r"(?P<)(?P[-\w.:|]*)(?P[\w\W]*)(?P>)", + r'(?P[\w_]{1,50})=(?P"?[\w_]+"?)?', + r"(?P[][{}()])", + _combine_regex( + r"(?P[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})", + r"(?P([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})", + r"(?P(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})", + r"(?P(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})", + r"(?P[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})", + r"(?P[\w.]*?)\(", + r"\b(?PTrue)\b|\b(?PFalse)\b|\b(?PNone)\b", + r"(?P\.\.\.)", + r"(?P(?(?\B(/[-\w._+]+)*\/)(?P[-\w._+]*)?", + r"(?b?'''.*?(?(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#~]*)", + ), + ] + + +class JSONHighlighter(RegexHighlighter): + """Highlights JSON""" + + # Captures the start and end of JSON strings, handling escaped quotes + JSON_STR = r"(?b?\".*?(?[\{\[\(\)\]\}])", + r"\b(?Ptrue)\b|\b(?Pfalse)\b|\b(?Pnull)\b", + r"(?P(? None: + super().highlight(text) + + # Additional work to handle highlighting JSON keys + plain = text.plain + append = text.spans.append + whitespace = self.JSON_WHITESPACE + for match in re.finditer(self.JSON_STR, plain): + start, end = match.span() + cursor = end + while cursor < len(plain): + char = plain[cursor] + cursor += 1 + if char == ":": + append(Span(start, end, "json.key")) + elif char in whitespace: + continue + break + + +class ISO8601Highlighter(RegexHighlighter): + """Highlights the ISO8601 date time strings. + Regex reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html + """ + + base_style = "iso8601." + highlights = [ + # + # Dates + # + # Calendar month (e.g. 2008-08). The hyphen is required + r"^(?P[0-9]{4})-(?P1[0-2]|0[1-9])$", + # Calendar date w/o hyphens (e.g. 20080830) + r"^(?P(?P[0-9]{4})(?P1[0-2]|0[1-9])(?P3[01]|0[1-9]|[12][0-9]))$", + # Ordinal date (e.g. 2008-243). The hyphen is optional + r"^(?P(?P[0-9]{4})-?(?P36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$", + # + # Weeks + # + # Week of the year (e.g., 2008-W35). The hyphen is optional + r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9]))$", + # Week date (e.g., 2008-W35-6). The hyphens are optional + r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9])-?(?P[1-7]))$", + # + # Times + # + # Hours and minutes (e.g., 17:21). The colon is optional + r"^(?P