From 909c38bc304ec5102a753e88041fd519725f430d Mon Sep 17 00:00:00 2001 From: Gaurav Date: Sun, 7 Jul 2024 22:37:59 +0530 Subject: [PATCH] Updated backend --- experiment/simulation/backend/Dockerfile | 12 - .../backend/exp_weighted_matching/__init__.py | 48 - .../exp_weighted_matching/anneal_wmp_det.m | 95 - .../exp_weighted_matching/anneal_wmp_mean.m | 113 - .../exp_weighted_matching/anneal_wmp_sto.m | 124 - .../exp_weighted_matching/applytofig.m | 19 - .../backend/exp_weighted_matching/drawgraph.m | 25 - .../backend/exp_weighted_matching/exportfig.m | 1057 --- .../backend/exp_weighted_matching/initMlp.m | 58 - .../backend/exp_weighted_matching/init_wmp.m | 30 - .../backend/exp_weighted_matching/initgraph.m | 12 - .../exp_weighted_matching/previewfig.m | 49 - .../exp_weighted_matching/restorefig.m | 19 - .../weightedmatchillustration.m | 85 - .../weightedmatching_det.m | 63 - .../weightedmatching_sto.m | 87 - .../simulation/backend/requirements.txt | 8 - experiment/simulation/backend/server.py | 141 - experiment/simulation/backend/swagger.yaml | 114 - experiment/simulation/backend/utils.py | 85 - .../simulation/backend/venv/bin/activate | 84 - .../simulation/backend/venv/bin/activate.csh | 55 - .../simulation/backend/venv/bin/activate.fish | 102 - .../simulation/backend/venv/bin/activate.ps1 | 60 - .../simulation/backend/venv/bin/activate.xsh | 46 - .../backend/venv/bin/activate_this.py | 46 - .../simulation/backend/venv/bin/easy_install | 8 - .../backend/venv/bin/easy_install-3.7 | 8 - experiment/simulation/backend/venv/bin/flask | 8 - experiment/simulation/backend/venv/bin/pip | 8 - experiment/simulation/backend/venv/bin/pip3 | 8 - experiment/simulation/backend/venv/bin/pip3.7 | 8 - experiment/simulation/backend/venv/bin/python | 1 - .../simulation/backend/venv/bin/python-config | 78 - .../simulation/backend/venv/bin/python3 | 1 - .../simulation/backend/venv/bin/python3.7 | Bin 14096 -> 0 bytes experiment/simulation/backend/venv/bin/wheel | 8 - .../backend/venv/include/python3.7m | 1 - .../backend/venv/lib/python3.7/LICENSE.txt | 1 - .../backend/venv/lib/python3.7/__future__.py | 146 - .../__pycache__/__future__.cpython-37.pyc | Bin 4175 -> 0 bytes .../__pycache__/_bootlocale.cpython-37.pyc | Bin 1292 -> 0 bytes .../_collections_abc.cpython-37.pyc | Bin 28985 -> 0 bytes .../__pycache__/_weakrefset.cpython-37.pyc | Bin 7505 -> 0 bytes .../python3.7/__pycache__/abc.cpython-37.pyc | Bin 6494 -> 0 bytes .../__pycache__/base64.cpython-37.pyc | Bin 17033 -> 0 bytes .../__pycache__/bisect.cpython-37.pyc | Bin 2741 -> 0 bytes .../__pycache__/codecs.cpython-37.pyc | Bin 34159 -> 0 bytes .../python3.7/__pycache__/copy.cpython-37.pyc | Bin 7166 -> 0 bytes .../__pycache__/copyreg.cpython-37.pyc | Bin 4287 -> 0 bytes .../python3.7/__pycache__/enum.cpython-37.pyc | Bin 24313 -> 0 bytes .../__pycache__/fnmatch.cpython-37.pyc | Bin 3380 -> 0 bytes .../__pycache__/functools.cpython-37.pyc | Bin 24274 -> 0 bytes .../__pycache__/genericpath.cpython-37.pyc | Bin 3947 -> 0 bytes .../__pycache__/hashlib.cpython-37.pyc | Bin 6634 -> 0 bytes .../__pycache__/heapq.cpython-37.pyc | Bin 14405 -> 0 bytes .../python3.7/__pycache__/hmac.cpython-37.pyc | Bin 6156 -> 0 bytes .../python3.7/__pycache__/io.cpython-37.pyc | Bin 3452 -> 0 bytes .../__pycache__/keyword.cpython-37.pyc | Bin 1852 -> 0 bytes .../__pycache__/linecache.cpython-37.pyc | Bin 3832 -> 0 bytes .../__pycache__/locale.cpython-37.pyc | Bin 34631 -> 0 bytes .../__pycache__/ntpath.cpython-37.pyc | Bin 13047 -> 0 bytes .../__pycache__/operator.cpython-37.pyc | Bin 13943 -> 0 bytes .../python3.7/__pycache__/os.cpython-37.pyc | Bin 29841 -> 0 bytes .../__pycache__/posixpath.cpython-37.pyc | Bin 10472 -> 0 bytes .../__pycache__/random.cpython-37.pyc | Bin 19451 -> 0 bytes .../python3.7/__pycache__/re.cpython-37.pyc | Bin 13847 -> 0 bytes .../__pycache__/reprlib.cpython-37.pyc | Bin 5393 -> 0 bytes .../__pycache__/shutil.cpython-37.pyc | Bin 31023 -> 0 bytes .../python3.7/__pycache__/site.cpython-37.pyc | Bin 21822 -> 0 bytes .../__pycache__/sre_compile.cpython-37.pyc | Bin 15246 -> 0 bytes .../__pycache__/sre_constants.cpython-37.pyc | Bin 6334 -> 0 bytes .../__pycache__/sre_parse.cpython-37.pyc | Bin 21329 -> 0 bytes .../python3.7/__pycache__/stat.cpython-37.pyc | Bin 4387 -> 0 bytes .../__pycache__/struct.cpython-37.pyc | Bin 377 -> 0 bytes .../__pycache__/tarfile.cpython-37.pyc | Bin 61902 -> 0 bytes .../__pycache__/tempfile.cpython-37.pyc | Bin 22275 -> 0 bytes .../__pycache__/token.cpython-37.pyc | Bin 3642 -> 0 bytes .../__pycache__/tokenize.cpython-37.pyc | Bin 17874 -> 0 bytes .../__pycache__/types.cpython-37.pyc | Bin 9019 -> 0 bytes .../__pycache__/warnings.cpython-37.pyc | Bin 13879 -> 0 bytes .../__pycache__/weakref.cpython-37.pyc | Bin 19612 -> 0 bytes .../backend/venv/lib/python3.7/_bootlocale.py | 46 - .../venv/lib/python3.7/_collections_abc.py | 1011 -- .../venv/lib/python3.7/_dummy_thread.py | 193 - .../backend/venv/lib/python3.7/_weakrefset.py | 196 - .../backend/venv/lib/python3.7/abc.py | 170 - .../backend/venv/lib/python3.7/base64.py | 595 -- .../backend/venv/lib/python3.7/bisect.py | 92 - .../backend/venv/lib/python3.7/codecs.py | 1125 --- .../backend/venv/lib/python3.7/collections | 1 - .../python3.7/config-3.7m-x86_64-linux-gnu | 1 - .../backend/venv/lib/python3.7/copy.py | 314 - .../backend/venv/lib/python3.7/copyreg.py | 206 - .../venv/lib/python3.7/distutils/__init__.py | 134 - .../__pycache__/__init__.cpython-37.pyc | Bin 3191 -> 0 bytes .../lib/python3.7/distutils/distutils.cfg | 6 - .../backend/venv/lib/python3.7/encodings | 1 - .../backend/venv/lib/python3.7/enum.py | 910 -- .../backend/venv/lib/python3.7/fnmatch.py | 128 - .../backend/venv/lib/python3.7/functools.py | 849 -- .../backend/venv/lib/python3.7/genericpath.py | 155 - .../backend/venv/lib/python3.7/hashlib.py | 252 - .../backend/venv/lib/python3.7/heapq.py | 607 -- .../backend/venv/lib/python3.7/hmac.py | 188 - .../backend/venv/lib/python3.7/imp.py | 345 - .../backend/venv/lib/python3.7/importlib | 1 - .../backend/venv/lib/python3.7/io.py | 99 - .../backend/venv/lib/python3.7/keyword.py | 96 - .../backend/venv/lib/python3.7/lib-dynload | 1 - .../backend/venv/lib/python3.7/linecache.py | 177 - .../backend/venv/lib/python3.7/locale.py | 1753 ---- .../lib/python3.7/no-global-site-packages.txt | 0 .../backend/venv/lib/python3.7/ntpath.py | 669 -- .../backend/venv/lib/python3.7/operator.py | 464 - .../venv/lib/python3.7/orig-prefix.txt | 1 - .../backend/venv/lib/python3.7/os.py | 1083 --- .../backend/venv/lib/python3.7/posixpath.py | 529 -- .../backend/venv/lib/python3.7/random.py | 777 -- .../backend/venv/lib/python3.7/re.py | 366 - .../backend/venv/lib/python3.7/reprlib.py | 161 - .../backend/venv/lib/python3.7/rlcompleter.py | 205 - .../backend/venv/lib/python3.7/shutil.py | 1188 --- .../Flask-1.1.2.dist-info/INSTALLER | 1 - .../Flask-1.1.2.dist-info/LICENSE.rst | 28 - .../Flask-1.1.2.dist-info/METADATA | 137 - .../Flask-1.1.2.dist-info/RECORD | 48 - .../site-packages/Flask-1.1.2.dist-info/WHEEL | 6 - .../Flask-1.1.2.dist-info/entry_points.txt | 3 - .../Flask-1.1.2.dist-info/top_level.txt | 1 - .../Flask_Cors-3.0.8.dist-info/INSTALLER | 1 - .../Flask_Cors-3.0.8.dist-info/LICENSE | 7 - .../Flask_Cors-3.0.8.dist-info/METADATA | 162 - .../Flask_Cors-3.0.8.dist-info/RECORD | 16 - .../Flask_Cors-3.0.8.dist-info/WHEEL | 6 - .../Flask_Cors-3.0.8.dist-info/top_level.txt | 1 - .../Jinja2-2.11.1.dist-info/INSTALLER | 1 - .../Jinja2-2.11.1.dist-info/LICENSE.rst | 28 - .../Jinja2-2.11.1.dist-info/METADATA | 106 - .../Jinja2-2.11.1.dist-info/RECORD | 61 - .../Jinja2-2.11.1.dist-info/WHEEL | 6 - .../Jinja2-2.11.1.dist-info/entry_points.txt | 3 - .../Jinja2-2.11.1.dist-info/top_level.txt | 1 - .../MarkupSafe-1.1.1.dist-info/INSTALLER | 1 - .../MarkupSafe-1.1.1.dist-info/LICENSE.txt | 28 - .../MarkupSafe-1.1.1.dist-info/METADATA | 103 - .../MarkupSafe-1.1.1.dist-info/RECORD | 16 - .../MarkupSafe-1.1.1.dist-info/WHEEL | 5 - .../MarkupSafe-1.1.1.dist-info/top_level.txt | 1 - .../Werkzeug-1.0.1.dist-info/INSTALLER | 1 - .../Werkzeug-1.0.1.dist-info/LICENSE.rst | 28 - .../Werkzeug-1.0.1.dist-info/METADATA | 128 - .../Werkzeug-1.0.1.dist-info/RECORD | 101 - .../Werkzeug-1.0.1.dist-info/WHEEL | 6 - .../Werkzeug-1.0.1.dist-info/top_level.txt | 1 - .../__pycache__/easy_install.cpython-37.pyc | Bin 281 -> 0 bytes .../__pycache__/six.cpython-37.pyc | Bin 26835 -> 0 bytes .../click-7.1.1.dist-info/INSTALLER | 1 - .../click-7.1.1.dist-info/LICENSE.rst | 28 - .../click-7.1.1.dist-info/METADATA | 102 - .../click-7.1.1.dist-info/RECORD | 40 - .../site-packages/click-7.1.1.dist-info/WHEEL | 6 - .../click-7.1.1.dist-info/top_level.txt | 1 - .../python3.7/site-packages/click/__init__.py | 79 - .../click/__pycache__/__init__.cpython-37.pyc | Bin 2696 -> 0 bytes .../__pycache__/_bashcomplete.cpython-37.pyc | Bin 9938 -> 0 bytes .../click/__pycache__/_compat.cpython-37.pyc | Bin 18587 -> 0 bytes .../__pycache__/_termui_impl.cpython-37.pyc | Bin 14137 -> 0 bytes .../__pycache__/_textwrap.cpython-37.pyc | Bin 1299 -> 0 bytes .../__pycache__/_unicodefun.cpython-37.pyc | Bin 3271 -> 0 bytes .../__pycache__/_winconsole.cpython-37.pyc | Bin 9366 -> 0 bytes .../click/__pycache__/core.cpython-37.pyc | Bin 61733 -> 0 bytes .../__pycache__/decorators.cpython-37.pyc | Bin 11631 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 9031 -> 0 bytes .../__pycache__/formatting.cpython-37.pyc | Bin 8662 -> 0 bytes .../click/__pycache__/globals.cpython-37.pyc | Bin 1833 -> 0 bytes .../click/__pycache__/parser.cpython-37.pyc | Bin 11747 -> 0 bytes .../click/__pycache__/termui.cpython-37.pyc | Bin 21508 -> 0 bytes .../click/__pycache__/testing.cpython-37.pyc | Bin 11635 -> 0 bytes .../click/__pycache__/types.cpython-37.pyc | Bin 22375 -> 0 bytes .../click/__pycache__/utils.cpython-37.pyc | Bin 15442 -> 0 bytes .../site-packages/click/_bashcomplete.py | 375 - .../python3.7/site-packages/click/_compat.py | 790 -- .../site-packages/click/_termui_impl.py | 661 -- .../site-packages/click/_textwrap.py | 37 - .../site-packages/click/_unicodefun.py | 131 - .../site-packages/click/_winconsole.py | 370 - .../lib/python3.7/site-packages/click/core.py | 2030 ---- .../site-packages/click/decorators.py | 333 - .../site-packages/click/exceptions.py | 253 - .../site-packages/click/formatting.py | 283 - .../python3.7/site-packages/click/globals.py | 47 - .../python3.7/site-packages/click/parser.py | 428 - .../python3.7/site-packages/click/termui.py | 681 -- .../python3.7/site-packages/click/testing.py | 382 - .../python3.7/site-packages/click/types.py | 762 -- .../python3.7/site-packages/click/utils.py | 455 - .../python3.7/site-packages/easy_install.py | 5 - .../python3.7/site-packages/flask/__init__.py | 60 - .../python3.7/site-packages/flask/__main__.py | 15 - .../flask/__pycache__/__init__.cpython-37.pyc | Bin 2093 -> 0 bytes .../flask/__pycache__/__main__.cpython-37.pyc | Bin 385 -> 0 bytes .../flask/__pycache__/_compat.cpython-37.pyc | Bin 4590 -> 0 bytes .../flask/__pycache__/app.cpython-37.pyc | Bin 74504 -> 0 bytes .../__pycache__/blueprints.cpython-37.pyc | Bin 22895 -> 0 bytes .../flask/__pycache__/cli.cpython-37.pyc | Bin 26205 -> 0 bytes .../flask/__pycache__/config.cpython-37.pyc | Bin 10130 -> 0 bytes .../flask/__pycache__/ctx.cpython-37.pyc | Bin 14291 -> 0 bytes .../__pycache__/debughelpers.cpython-37.pyc | Bin 6551 -> 0 bytes .../flask/__pycache__/globals.cpython-37.pyc | Bin 1697 -> 0 bytes .../flask/__pycache__/helpers.cpython-37.pyc | Bin 34512 -> 0 bytes .../flask/__pycache__/logging.cpython-37.pyc | Bin 3092 -> 0 bytes .../flask/__pycache__/sessions.cpython-37.pyc | Bin 12189 -> 0 bytes .../flask/__pycache__/signals.cpython-37.pyc | Bin 2370 -> 0 bytes .../__pycache__/templating.cpython-37.pyc | Bin 4949 -> 0 bytes .../flask/__pycache__/testing.cpython-37.pyc | Bin 8656 -> 0 bytes .../flask/__pycache__/views.cpython-37.pyc | Bin 4771 -> 0 bytes .../flask/__pycache__/wrappers.cpython-37.pyc | Bin 4257 -> 0 bytes .../python3.7/site-packages/flask/_compat.py | 145 - .../lib/python3.7/site-packages/flask/app.py | 2467 ----- .../site-packages/flask/blueprints.py | 569 -- .../lib/python3.7/site-packages/flask/cli.py | 971 -- .../python3.7/site-packages/flask/config.py | 269 - .../lib/python3.7/site-packages/flask/ctx.py | 475 - .../site-packages/flask/debughelpers.py | 183 - .../python3.7/site-packages/flask/globals.py | 62 - .../python3.7/site-packages/flask/helpers.py | 1155 --- .../site-packages/flask/json/__init__.py | 376 - .../json/__pycache__/__init__.cpython-37.pyc | Bin 11543 -> 0 bytes .../flask/json/__pycache__/tag.cpython-37.pyc | Bin 11070 -> 0 bytes .../python3.7/site-packages/flask/json/tag.py | 309 - .../python3.7/site-packages/flask/logging.py | 109 - .../python3.7/site-packages/flask/sessions.py | 388 - .../python3.7/site-packages/flask/signals.py | 65 - .../site-packages/flask/templating.py | 155 - .../python3.7/site-packages/flask/testing.py | 283 - .../python3.7/site-packages/flask/views.py | 163 - .../python3.7/site-packages/flask/wrappers.py | 137 - .../site-packages/flask_cors/__init__.py | 27 - .../__pycache__/__init__.cpython-37.pyc | Bin 757 -> 0 bytes .../__pycache__/core.cpython-37.pyc | Bin 10346 -> 0 bytes .../__pycache__/decorator.cpython-37.pyc | Bin 4660 -> 0 bytes .../__pycache__/extension.cpython-37.pyc | Bin 7009 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 162 -> 0 bytes .../site-packages/flask_cors/core.py | 383 - .../site-packages/flask_cors/decorator.py | 135 - .../site-packages/flask_cors/extension.py | 186 - .../site-packages/flask_cors/version.py | 1 - .../itsdangerous-1.1.0.dist-info/INSTALLER | 1 - .../itsdangerous-1.1.0.dist-info/LICENSE.rst | 47 - .../itsdangerous-1.1.0.dist-info/METADATA | 98 - .../itsdangerous-1.1.0.dist-info/RECORD | 26 - .../itsdangerous-1.1.0.dist-info/WHEEL | 6 - .../top_level.txt | 1 - .../site-packages/itsdangerous/__init__.py | 22 - .../__pycache__/__init__.cpython-37.pyc | Bin 972 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 1134 -> 0 bytes .../__pycache__/_json.cpython-37.pyc | Bin 817 -> 0 bytes .../__pycache__/encoding.cpython-37.pyc | Bin 1599 -> 0 bytes .../__pycache__/exc.cpython-37.pyc | Bin 3188 -> 0 bytes .../__pycache__/jws.cpython-37.pyc | Bin 6647 -> 0 bytes .../__pycache__/serializer.cpython-37.pyc | Bin 8003 -> 0 bytes .../__pycache__/signer.cpython-37.pyc | Bin 5763 -> 0 bytes .../__pycache__/timed.cpython-37.pyc | Bin 4529 -> 0 bytes .../__pycache__/url_safe.cpython-37.pyc | Bin 2518 -> 0 bytes .../site-packages/itsdangerous/_compat.py | 46 - .../site-packages/itsdangerous/_json.py | 18 - .../site-packages/itsdangerous/encoding.py | 49 - .../site-packages/itsdangerous/exc.py | 98 - .../site-packages/itsdangerous/jws.py | 218 - .../site-packages/itsdangerous/serializer.py | 233 - .../site-packages/itsdangerous/signer.py | 179 - .../site-packages/itsdangerous/timed.py | 147 - .../site-packages/itsdangerous/url_safe.py | 65 - .../site-packages/jinja2/__init__.py | 44 - .../__pycache__/__init__.cpython-37.pyc | Bin 1775 -> 0 bytes .../jinja2/__pycache__/_compat.cpython-37.pyc | Bin 3809 -> 0 bytes .../__pycache__/_identifier.cpython-37.pyc | Bin 1856 -> 0 bytes .../__pycache__/asyncfilters.cpython-37.pyc | Bin 4790 -> 0 bytes .../__pycache__/asyncsupport.cpython-37.pyc | Bin 8208 -> 0 bytes .../jinja2/__pycache__/bccache.cpython-37.pyc | Bin 12102 -> 0 bytes .../__pycache__/compiler.cpython-37.pyc | Bin 48640 -> 0 bytes .../__pycache__/constants.cpython-37.pyc | Bin 1502 -> 0 bytes .../jinja2/__pycache__/debug.cpython-37.pyc | Bin 5139 -> 0 bytes .../__pycache__/defaults.cpython-37.pyc | Bin 1074 -> 0 bytes .../__pycache__/environment.cpython-37.pyc | Bin 43835 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 5619 -> 0 bytes .../jinja2/__pycache__/ext.cpython-37.pyc | Bin 21348 -> 0 bytes .../jinja2/__pycache__/filters.cpython-37.pyc | Bin 39506 -> 0 bytes .../__pycache__/idtracking.cpython-37.pyc | Bin 9912 -> 0 bytes .../jinja2/__pycache__/lexer.cpython-37.pyc | Bin 18877 -> 0 bytes .../jinja2/__pycache__/loaders.cpython-37.pyc | Bin 18126 -> 0 bytes .../jinja2/__pycache__/meta.cpython-37.pyc | Bin 3440 -> 0 bytes .../__pycache__/nativetypes.cpython-37.pyc | Bin 4168 -> 0 bytes .../jinja2/__pycache__/nodes.cpython-37.pyc | Bin 36371 -> 0 bytes .../__pycache__/optimizer.cpython-37.pyc | Bin 1602 -> 0 bytes .../jinja2/__pycache__/parser.cpython-37.pyc | Bin 25076 -> 0 bytes .../jinja2/__pycache__/runtime.cpython-37.pyc | Bin 27226 -> 0 bytes .../jinja2/__pycache__/sandbox.cpython-37.pyc | Bin 13951 -> 0 bytes .../jinja2/__pycache__/tests.cpython-37.pyc | Bin 5286 -> 0 bytes .../jinja2/__pycache__/utils.cpython-37.pyc | Bin 22644 -> 0 bytes .../jinja2/__pycache__/visitor.cpython-37.pyc | Bin 3247 -> 0 bytes .../python3.7/site-packages/jinja2/_compat.py | 132 - .../site-packages/jinja2/_identifier.py | 6 - .../site-packages/jinja2/asyncfilters.py | 159 - .../site-packages/jinja2/asyncsupport.py | 264 - .../python3.7/site-packages/jinja2/bccache.py | 350 - .../site-packages/jinja2/compiler.py | 1843 ---- .../site-packages/jinja2/constants.py | 21 - .../python3.7/site-packages/jinja2/debug.py | 271 - .../site-packages/jinja2/defaults.py | 44 - .../site-packages/jinja2/environment.py | 1362 --- .../site-packages/jinja2/exceptions.py | 177 - .../lib/python3.7/site-packages/jinja2/ext.py | 704 -- .../python3.7/site-packages/jinja2/filters.py | 1382 --- .../site-packages/jinja2/idtracking.py | 290 - .../python3.7/site-packages/jinja2/lexer.py | 841 -- .../python3.7/site-packages/jinja2/loaders.py | 572 -- .../python3.7/site-packages/jinja2/meta.py | 101 - .../site-packages/jinja2/nativetypes.py | 111 - .../python3.7/site-packages/jinja2/nodes.py | 1088 --- .../site-packages/jinja2/optimizer.py | 41 - .../python3.7/site-packages/jinja2/parser.py | 939 -- .../python3.7/site-packages/jinja2/runtime.py | 1011 -- .../python3.7/site-packages/jinja2/sandbox.py | 510 - .../python3.7/site-packages/jinja2/tests.py | 215 - .../python3.7/site-packages/jinja2/utils.py | 727 -- .../python3.7/site-packages/jinja2/visitor.py | 81 - .../site-packages/markupsafe/__init__.py | 327 - .../__pycache__/__init__.cpython-37.pyc | Bin 10820 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 727 -> 0 bytes .../__pycache__/_constants.cpython-37.pyc | Bin 4227 -> 0 bytes .../__pycache__/_native.cpython-37.pyc | Bin 2079 -> 0 bytes .../site-packages/markupsafe/_compat.py | 33 - .../site-packages/markupsafe/_constants.py | 264 - .../site-packages/markupsafe/_native.py | 69 - .../site-packages/markupsafe/_speedups.c | 423 - .../_speedups.cpython-37m-x86_64-linux-gnu.so | Bin 38875 -> 0 bytes .../pip-20.0.2.dist-info/INSTALLER | 1 - .../pip-20.0.2.dist-info/LICENSE.txt | 20 - .../pip-20.0.2.dist-info/METADATA | 84 - .../site-packages/pip-20.0.2.dist-info/RECORD | 704 -- .../site-packages/pip-20.0.2.dist-info/WHEEL | 6 - .../pip-20.0.2.dist-info/entry_points.txt | 5 - .../pip-20.0.2.dist-info/top_level.txt | 1 - .../python3.7/site-packages/pip/__init__.py | 18 - .../python3.7/site-packages/pip/__main__.py | 19 - .../pip/__pycache__/__init__.cpython-37.pyc | Bin 618 -> 0 bytes .../pip/__pycache__/__main__.cpython-37.pyc | Bin 415 -> 0 bytes .../site-packages/pip/_internal/__init__.py | 18 - .../__pycache__/__init__.cpython-37.pyc | Bin 667 -> 0 bytes .../__pycache__/build_env.cpython-37.pyc | Bin 7391 -> 0 bytes .../__pycache__/cache.cpython-37.pyc | Bin 8624 -> 0 bytes .../__pycache__/configuration.cpython-37.pyc | Bin 10510 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 12686 -> 0 bytes .../__pycache__/legacy_resolve.cpython-37.pyc | Bin 9876 -> 0 bytes .../__pycache__/locations.cpython-37.pyc | Bin 4435 -> 0 bytes .../_internal/__pycache__/main.cpython-37.pyc | Bin 604 -> 0 bytes .../__pycache__/pep425tags.cpython-37.pyc | Bin 3529 -> 0 bytes .../__pycache__/pyproject.cpython-37.pyc | Bin 3691 -> 0 bytes .../self_outdated_check.cpython-37.pyc | Bin 5398 -> 0 bytes .../__pycache__/wheel_builder.cpython-37.pyc | Bin 6573 -> 0 bytes .../site-packages/pip/_internal/build_env.py | 221 - .../site-packages/pip/_internal/cache.py | 329 - .../pip/_internal/cli/__init__.py | 4 - .../cli/__pycache__/__init__.cpython-37.pyc | Bin 229 -> 0 bytes .../__pycache__/autocompletion.cpython-37.pyc | Bin 4925 -> 0 bytes .../__pycache__/base_command.cpython-37.pyc | Bin 5709 -> 0 bytes .../cli/__pycache__/cmdoptions.cpython-37.pyc | Bin 20164 -> 0 bytes .../command_context.cpython-37.pyc | Bin 1290 -> 0 bytes .../cli/__pycache__/main.cpython-37.pyc | Bin 1395 -> 0 bytes .../__pycache__/main_parser.cpython-37.pyc | Bin 2136 -> 0 bytes .../cli/__pycache__/parser.cpython-37.pyc | Bin 8893 -> 0 bytes .../__pycache__/req_command.cpython-37.pyc | Bin 8184 -> 0 bytes .../__pycache__/status_codes.cpython-37.pyc | Bin 358 -> 0 bytes .../pip/_internal/cli/autocompletion.py | 164 - .../pip/_internal/cli/base_command.py | 226 - .../pip/_internal/cli/cmdoptions.py | 957 -- .../pip/_internal/cli/command_context.py | 36 - .../site-packages/pip/_internal/cli/main.py | 75 - .../pip/_internal/cli/main_parser.py | 99 - .../site-packages/pip/_internal/cli/parser.py | 265 - .../pip/_internal/cli/req_command.py | 333 - .../pip/_internal/cli/status_codes.py | 8 - .../pip/_internal/commands/__init__.py | 114 - .../__pycache__/__init__.cpython-37.pyc | Bin 2779 -> 0 bytes .../commands/__pycache__/check.cpython-37.pyc | Bin 1297 -> 0 bytes .../__pycache__/completion.cpython-37.pyc | Bin 2968 -> 0 bytes .../__pycache__/configuration.cpython-37.pyc | Bin 6510 -> 0 bytes .../commands/__pycache__/debug.cpython-37.pyc | Bin 4044 -> 0 bytes .../__pycache__/download.cpython-37.pyc | Bin 3872 -> 0 bytes .../__pycache__/freeze.cpython-37.pyc | Bin 2890 -> 0 bytes .../commands/__pycache__/hash.cpython-37.pyc | Bin 1966 -> 0 bytes .../commands/__pycache__/help.cpython-37.pyc | Bin 1167 -> 0 bytes .../__pycache__/install.cpython-37.pyc | Bin 15936 -> 0 bytes .../commands/__pycache__/list.cpython-37.pyc | Bin 8839 -> 0 bytes .../__pycache__/search.cpython-37.pyc | Bin 4435 -> 0 bytes .../commands/__pycache__/show.cpython-37.pyc | Bin 6322 -> 0 bytes .../__pycache__/uninstall.cpython-37.pyc | Bin 2669 -> 0 bytes .../commands/__pycache__/wheel.cpython-37.pyc | Bin 5183 -> 0 bytes .../pip/_internal/commands/check.py | 45 - .../pip/_internal/commands/completion.py | 96 - .../pip/_internal/commands/configuration.py | 233 - .../pip/_internal/commands/debug.py | 142 - .../pip/_internal/commands/download.py | 147 - .../pip/_internal/commands/freeze.py | 103 - .../pip/_internal/commands/hash.py | 58 - .../pip/_internal/commands/help.py | 41 - .../pip/_internal/commands/install.py | 701 -- .../pip/_internal/commands/list.py | 313 - .../pip/_internal/commands/search.py | 145 - .../pip/_internal/commands/show.py | 180 - .../pip/_internal/commands/uninstall.py | 82 - .../pip/_internal/commands/wheel.py | 197 - .../pip/_internal/configuration.py | 422 - .../pip/_internal/distributions/__init__.py | 24 - .../__pycache__/__init__.cpython-37.pyc | Bin 801 -> 0 bytes .../__pycache__/base.cpython-37.pyc | Bin 1901 -> 0 bytes .../__pycache__/installed.cpython-37.pyc | Bin 1187 -> 0 bytes .../__pycache__/sdist.cpython-37.pyc | Bin 3417 -> 0 bytes .../__pycache__/wheel.cpython-37.pyc | Bin 1523 -> 0 bytes .../pip/_internal/distributions/base.py | 45 - .../pip/_internal/distributions/installed.py | 24 - .../pip/_internal/distributions/sdist.py | 104 - .../pip/_internal/distributions/wheel.py | 36 - .../site-packages/pip/_internal/exceptions.py | 308 - .../pip/_internal/index/__init__.py | 2 - .../index/__pycache__/__init__.cpython-37.pyc | Bin 183 -> 0 bytes .../__pycache__/collector.cpython-37.pyc | Bin 14036 -> 0 bytes .../__pycache__/package_finder.cpython-37.pyc | Bin 25473 -> 0 bytes .../pip/_internal/index/collector.py | 544 -- .../pip/_internal/index/package_finder.py | 1013 -- .../pip/_internal/legacy_resolve.py | 430 - .../site-packages/pip/_internal/locations.py | 194 - .../site-packages/pip/_internal/main.py | 16 - .../pip/_internal/models/__init__.py | 2 - .../__pycache__/__init__.cpython-37.pyc | Bin 217 -> 0 bytes .../__pycache__/candidate.cpython-37.pyc | Bin 1405 -> 0 bytes .../__pycache__/format_control.cpython-37.pyc | Bin 2382 -> 0 bytes .../models/__pycache__/index.cpython-37.pyc | Bin 1121 -> 0 bytes .../models/__pycache__/link.cpython-37.pyc | Bin 6567 -> 0 bytes .../models/__pycache__/scheme.cpython-37.pyc | Bin 847 -> 0 bytes .../__pycache__/search_scope.cpython-37.pyc | Bin 3213 -> 0 bytes .../selection_prefs.cpython-37.pyc | Bin 1579 -> 0 bytes .../__pycache__/target_python.cpython-37.pyc | Bin 3174 -> 0 bytes .../models/__pycache__/wheel.cpython-37.pyc | Bin 3141 -> 0 bytes .../pip/_internal/models/candidate.py | 36 - .../pip/_internal/models/format_control.py | 84 - .../pip/_internal/models/index.py | 31 - .../pip/_internal/models/link.py | 227 - .../pip/_internal/models/scheme.py | 25 - .../pip/_internal/models/search_scope.py | 114 - .../pip/_internal/models/selection_prefs.py | 47 - .../pip/_internal/models/target_python.py | 107 - .../pip/_internal/models/wheel.py | 78 - .../pip/_internal/network/__init__.py | 2 - .../__pycache__/__init__.cpython-37.pyc | Bin 205 -> 0 bytes .../network/__pycache__/auth.cpython-37.pyc | Bin 6923 -> 0 bytes .../network/__pycache__/cache.cpython-37.pyc | Bin 2626 -> 0 bytes .../__pycache__/download.cpython-37.pyc | Bin 4295 -> 0 bytes .../__pycache__/session.cpython-37.pyc | Bin 8735 -> 0 bytes .../network/__pycache__/utils.cpython-37.pyc | Bin 703 -> 0 bytes .../network/__pycache__/xmlrpc.cpython-37.pyc | Bin 1545 -> 0 bytes .../pip/_internal/network/auth.py | 298 - .../pip/_internal/network/cache.py | 81 - .../pip/_internal/network/download.py | 200 - .../pip/_internal/network/session.py | 405 - .../pip/_internal/network/utils.py | 48 - .../pip/_internal/network/xmlrpc.py | 44 - .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 153 -> 0 bytes .../__pycache__/check.cpython-37.pyc | Bin 3639 -> 0 bytes .../__pycache__/freeze.cpython-37.pyc | Bin 5716 -> 0 bytes .../__pycache__/prepare.cpython-37.pyc | Bin 10995 -> 0 bytes .../pip/_internal/operations/check.py | 163 - .../pip/_internal/operations/freeze.py | 265 - .../_internal/operations/install/__init__.py | 2 - .../__pycache__/__init__.cpython-37.pyc | Bin 217 -> 0 bytes .../editable_legacy.cpython-37.pyc | Bin 1287 -> 0 bytes .../install/__pycache__/legacy.cpython-37.pyc | Bin 3009 -> 0 bytes .../install/__pycache__/wheel.cpython-37.pyc | Bin 14421 -> 0 bytes .../operations/install/editable_legacy.py | 52 - .../_internal/operations/install/legacy.py | 129 - .../pip/_internal/operations/install/wheel.py | 615 -- .../pip/_internal/operations/prepare.py | 591 -- .../site-packages/pip/_internal/pep425tags.py | 167 - .../site-packages/pip/_internal/pyproject.py | 196 - .../pip/_internal/req/__init__.py | 92 - .../req/__pycache__/__init__.cpython-37.pyc | Bin 2150 -> 0 bytes .../__pycache__/constructors.cpython-37.pyc | Bin 10215 -> 0 bytes .../req/__pycache__/req_file.cpython-37.pyc | Bin 12587 -> 0 bytes .../__pycache__/req_install.cpython-37.pyc | Bin 21100 -> 0 bytes .../req/__pycache__/req_set.cpython-37.pyc | Bin 5934 -> 0 bytes .../__pycache__/req_tracker.cpython-37.pyc | Bin 4002 -> 0 bytes .../__pycache__/req_uninstall.cpython-37.pyc | Bin 17314 -> 0 bytes .../pip/_internal/req/constructors.py | 436 - .../pip/_internal/req/req_file.py | 546 -- .../pip/_internal/req/req_install.py | 830 -- .../pip/_internal/req/req_set.py | 209 - .../pip/_internal/req/req_tracker.py | 150 - .../pip/_internal/req/req_uninstall.py | 644 -- .../pip/_internal/self_outdated_check.py | 242 - .../pip/_internal/utils/__init__.py | 0 .../utils/__pycache__/__init__.cpython-37.pyc | Bin 148 -> 0 bytes .../utils/__pycache__/appdirs.cpython-37.pyc | Bin 1334 -> 0 bytes .../utils/__pycache__/compat.cpython-37.pyc | Bin 6150 -> 0 bytes .../__pycache__/deprecation.cpython-37.pyc | Bin 2765 -> 0 bytes .../__pycache__/distutils_args.cpython-37.pyc | Bin 1130 -> 0 bytes .../utils/__pycache__/encoding.cpython-37.pyc | Bin 1232 -> 0 bytes .../__pycache__/entrypoints.cpython-37.pyc | Bin 1286 -> 0 bytes .../__pycache__/filesystem.cpython-37.pyc | Bin 3970 -> 0 bytes .../__pycache__/filetypes.cpython-37.pyc | Bin 547 -> 0 bytes .../utils/__pycache__/glibc.cpython-37.pyc | Bin 1679 -> 0 bytes .../utils/__pycache__/hashes.cpython-37.pyc | Bin 4088 -> 0 bytes .../inject_securetransport.cpython-37.pyc | Bin 917 -> 0 bytes .../utils/__pycache__/logging.cpython-37.pyc | Bin 9119 -> 0 bytes .../__pycache__/marker_files.cpython-37.pyc | Bin 913 -> 0 bytes .../utils/__pycache__/misc.cpython-37.pyc | Bin 22892 -> 0 bytes .../utils/__pycache__/models.cpython-37.pyc | Bin 1896 -> 0 bytes .../__pycache__/packaging.cpython-37.pyc | Bin 2583 -> 0 bytes .../__pycache__/pkg_resources.cpython-37.pyc | Bin 1796 -> 0 bytes .../setuptools_build.cpython-37.pyc | Bin 2929 -> 0 bytes .../__pycache__/subprocess.cpython-37.pyc | Bin 5528 -> 0 bytes .../utils/__pycache__/temp_dir.cpython-37.pyc | Bin 6672 -> 0 bytes .../utils/__pycache__/typing.cpython-37.pyc | Bin 1426 -> 0 bytes .../utils/__pycache__/ui.cpython-37.pyc | Bin 11689 -> 0 bytes .../__pycache__/unpacking.cpython-37.pyc | Bin 5974 -> 0 bytes .../utils/__pycache__/urls.cpython-37.pyc | Bin 1442 -> 0 bytes .../__pycache__/virtualenv.cpython-37.pyc | Bin 3223 -> 0 bytes .../utils/__pycache__/wheel.cpython-37.pyc | Bin 6249 -> 0 bytes .../pip/_internal/utils/appdirs.py | 41 - .../pip/_internal/utils/compat.py | 269 - .../pip/_internal/utils/deprecation.py | 104 - .../pip/_internal/utils/distutils_args.py | 48 - .../pip/_internal/utils/encoding.py | 42 - .../pip/_internal/utils/entrypoints.py | 31 - .../pip/_internal/utils/filesystem.py | 171 - .../pip/_internal/utils/filetypes.py | 16 - .../pip/_internal/utils/glibc.py | 98 - .../pip/_internal/utils/hashes.py | 131 - .../_internal/utils/inject_securetransport.py | 36 - .../pip/_internal/utils/logging.py | 398 - .../pip/_internal/utils/marker_files.py | 25 - .../site-packages/pip/_internal/utils/misc.py | 886 -- .../pip/_internal/utils/models.py | 42 - .../pip/_internal/utils/packaging.py | 94 - .../pip/_internal/utils/pkg_resources.py | 44 - .../pip/_internal/utils/setuptools_build.py | 181 - .../pip/_internal/utils/subprocess.py | 278 - .../pip/_internal/utils/temp_dir.py | 250 - .../pip/_internal/utils/typing.py | 38 - .../site-packages/pip/_internal/utils/ui.py | 428 - .../pip/_internal/utils/unpacking.py | 272 - .../site-packages/pip/_internal/utils/urls.py | 54 - .../pip/_internal/utils/virtualenv.py | 115 - .../pip/_internal/utils/wheel.py | 225 - .../pip/_internal/vcs/__init__.py | 15 - .../vcs/__pycache__/__init__.cpython-37.pyc | Bin 441 -> 0 bytes .../vcs/__pycache__/bazaar.cpython-37.pyc | Bin 3678 -> 0 bytes .../vcs/__pycache__/git.cpython-37.pyc | Bin 9390 -> 0 bytes .../vcs/__pycache__/mercurial.cpython-37.pyc | Bin 4818 -> 0 bytes .../vcs/__pycache__/subversion.cpython-37.pyc | Bin 8393 -> 0 bytes .../__pycache__/versioncontrol.cpython-37.pyc | Bin 19081 -> 0 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 120 - .../site-packages/pip/_internal/vcs/git.py | 389 - .../pip/_internal/vcs/mercurial.py | 155 - .../pip/_internal/vcs/subversion.py | 333 - .../pip/_internal/vcs/versioncontrol.py | 700 -- .../pip/_internal/wheel_builder.py | 305 - .../site-packages/pip/_vendor/__init__.py | 109 - .../__pycache__/__init__.cpython-37.pyc | Bin 2818 -> 0 bytes .../__pycache__/appdirs.cpython-37.pyc | Bin 21459 -> 0 bytes .../__pycache__/contextlib2.cpython-37.pyc | Bin 15323 -> 0 bytes .../_vendor/__pycache__/distro.cpython-37.pyc | Bin 36278 -> 0 bytes .../__pycache__/ipaddress.cpython-37.pyc | Bin 66412 -> 0 bytes .../__pycache__/pyparsing.cpython-37.pyc | Bin 241952 -> 0 bytes .../__pycache__/retrying.cpython-37.pyc | Bin 8046 -> 0 bytes .../_vendor/__pycache__/six.cpython-37.pyc | Bin 26844 -> 0 bytes .../site-packages/pip/_vendor/appdirs.py | 639 -- .../pip/_vendor/cachecontrol/__init__.py | 11 - .../__pycache__/__init__.cpython-37.pyc | Bin 506 -> 0 bytes .../__pycache__/_cmd.cpython-37.pyc | Bin 1509 -> 0 bytes .../__pycache__/adapter.cpython-37.pyc | Bin 3000 -> 0 bytes .../__pycache__/cache.cpython-37.pyc | Bin 1722 -> 0 bytes .../__pycache__/compat.cpython-37.pyc | Bin 713 -> 0 bytes .../__pycache__/controller.cpython-37.pyc | Bin 7683 -> 0 bytes .../__pycache__/filewrapper.cpython-37.pyc | Bin 2110 -> 0 bytes .../__pycache__/heuristics.cpython-37.pyc | Bin 4630 -> 0 bytes .../__pycache__/serialize.cpython-37.pyc | Bin 4183 -> 0 bytes .../__pycache__/wrapper.cpython-37.pyc | Bin 622 -> 0 bytes .../pip/_vendor/cachecontrol/_cmd.py | 57 - .../pip/_vendor/cachecontrol/adapter.py | 133 - .../pip/_vendor/cachecontrol/cache.py | 39 - .../_vendor/cachecontrol/caches/__init__.py | 2 - .../__pycache__/__init__.cpython-37.pyc | Bin 250 -> 0 bytes .../__pycache__/file_cache.cpython-37.pyc | Bin 3160 -> 0 bytes .../__pycache__/redis_cache.cpython-37.pyc | Bin 1506 -> 0 bytes .../_vendor/cachecontrol/caches/file_cache.py | 146 - .../cachecontrol/caches/redis_cache.py | 33 - .../pip/_vendor/cachecontrol/compat.py | 29 - .../pip/_vendor/cachecontrol/controller.py | 376 - .../pip/_vendor/cachecontrol/filewrapper.py | 80 - .../pip/_vendor/cachecontrol/heuristics.py | 135 - .../pip/_vendor/cachecontrol/serialize.py | 188 - .../pip/_vendor/cachecontrol/wrapper.py | 29 - .../pip/_vendor/certifi/__init__.py | 3 - .../pip/_vendor/certifi/__main__.py | 2 - .../__pycache__/__init__.cpython-37.pyc | Bin 213 -> 0 bytes .../__pycache__/__main__.cpython-37.pyc | Bin 216 -> 0 bytes .../certifi/__pycache__/core.cpython-37.pyc | Bin 425 -> 0 bytes .../pip/_vendor/certifi/cacert.pem | 4602 --------- .../site-packages/pip/_vendor/certifi/core.py | 15 - .../pip/_vendor/chardet/__init__.py | 39 - .../__pycache__/__init__.cpython-37.pyc | Bin 800 -> 0 bytes .../__pycache__/big5freq.cpython-37.pyc | Bin 27135 -> 0 bytes .../__pycache__/big5prober.cpython-37.pyc | Bin 1076 -> 0 bytes .../chardistribution.cpython-37.pyc | Bin 6262 -> 0 bytes .../charsetgroupprober.cpython-37.pyc | Bin 2183 -> 0 bytes .../__pycache__/charsetprober.cpython-37.pyc | Bin 3393 -> 0 bytes .../codingstatemachine.cpython-37.pyc | Bin 2840 -> 0 bytes .../chardet/__pycache__/compat.cpython-37.pyc | Bin 311 -> 0 bytes .../__pycache__/cp949prober.cpython-37.pyc | Bin 1083 -> 0 bytes .../chardet/__pycache__/enums.cpython-37.pyc | Bin 2574 -> 0 bytes .../__pycache__/escprober.cpython-37.pyc | Bin 2561 -> 0 bytes .../chardet/__pycache__/escsm.cpython-37.pyc | Bin 7022 -> 0 bytes .../__pycache__/eucjpprober.cpython-37.pyc | Bin 2369 -> 0 bytes .../__pycache__/euckrfreq.cpython-37.pyc | Bin 12019 -> 0 bytes .../__pycache__/euckrprober.cpython-37.pyc | Bin 1084 -> 0 bytes .../__pycache__/euctwfreq.cpython-37.pyc | Bin 27139 -> 0 bytes .../__pycache__/euctwprober.cpython-37.pyc | Bin 1084 -> 0 bytes .../__pycache__/gb2312freq.cpython-37.pyc | Bin 19063 -> 0 bytes .../__pycache__/gb2312prober.cpython-37.pyc | Bin 1092 -> 0 bytes .../__pycache__/hebrewprober.cpython-37.pyc | Bin 2926 -> 0 bytes .../__pycache__/jisfreq.cpython-37.pyc | Bin 22091 -> 0 bytes .../chardet/__pycache__/jpcntx.cpython-37.pyc | Bin 37970 -> 0 bytes .../langbulgarianmodel.cpython-37.pyc | Bin 23584 -> 0 bytes .../langcyrillicmodel.cpython-37.pyc | Bin 29040 -> 0 bytes .../__pycache__/langgreekmodel.cpython-37.pyc | Bin 23542 -> 0 bytes .../langhebrewmodel.cpython-37.pyc | Bin 22171 -> 0 bytes .../langhungarianmodel.cpython-37.pyc | Bin 23573 -> 0 bytes .../__pycache__/langthaimodel.cpython-37.pyc | Bin 22150 -> 0 bytes .../langturkishmodel.cpython-37.pyc | Bin 22173 -> 0 bytes .../__pycache__/latin1prober.cpython-37.pyc | Bin 2883 -> 0 bytes .../mbcharsetprober.cpython-37.pyc | Bin 2188 -> 0 bytes .../mbcsgroupprober.cpython-37.pyc | Bin 1079 -> 0 bytes .../chardet/__pycache__/mbcssm.cpython-37.pyc | Bin 15634 -> 0 bytes .../sbcharsetprober.cpython-37.pyc | Bin 2941 -> 0 bytes .../sbcsgroupprober.cpython-37.pyc | Bin 1569 -> 0 bytes .../__pycache__/sjisprober.cpython-37.pyc | Bin 2395 -> 0 bytes .../universaldetector.cpython-37.pyc | Bin 5785 -> 0 bytes .../__pycache__/utf8prober.cpython-37.pyc | Bin 1926 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 395 -> 0 bytes .../pip/_vendor/chardet/big5freq.py | 386 - .../pip/_vendor/chardet/big5prober.py | 47 - .../pip/_vendor/chardet/chardistribution.py | 233 - .../pip/_vendor/chardet/charsetgroupprober.py | 106 - .../pip/_vendor/chardet/charsetprober.py | 145 - .../pip/_vendor/chardet/cli/__init__.py | 1 - .../cli/__pycache__/__init__.cpython-37.pyc | Bin 152 -> 0 bytes .../cli/__pycache__/chardetect.cpython-37.pyc | Bin 2641 -> 0 bytes .../pip/_vendor/chardet/cli/chardetect.py | 85 - .../pip/_vendor/chardet/codingstatemachine.py | 88 - .../pip/_vendor/chardet/compat.py | 34 - .../pip/_vendor/chardet/cp949prober.py | 49 - .../pip/_vendor/chardet/enums.py | 76 - .../pip/_vendor/chardet/escprober.py | 101 - .../pip/_vendor/chardet/escsm.py | 246 - .../pip/_vendor/chardet/eucjpprober.py | 92 - .../pip/_vendor/chardet/euckrfreq.py | 195 - .../pip/_vendor/chardet/euckrprober.py | 47 - .../pip/_vendor/chardet/euctwfreq.py | 387 - .../pip/_vendor/chardet/euctwprober.py | 46 - .../pip/_vendor/chardet/gb2312freq.py | 283 - .../pip/_vendor/chardet/gb2312prober.py | 46 - .../pip/_vendor/chardet/hebrewprober.py | 292 - .../pip/_vendor/chardet/jisfreq.py | 325 - .../pip/_vendor/chardet/jpcntx.py | 233 - .../pip/_vendor/chardet/langbulgarianmodel.py | 228 - .../pip/_vendor/chardet/langcyrillicmodel.py | 333 - .../pip/_vendor/chardet/langgreekmodel.py | 225 - .../pip/_vendor/chardet/langhebrewmodel.py | 200 - .../pip/_vendor/chardet/langhungarianmodel.py | 225 - .../pip/_vendor/chardet/langthaimodel.py | 199 - .../pip/_vendor/chardet/langturkishmodel.py | 193 - .../pip/_vendor/chardet/latin1prober.py | 145 - .../pip/_vendor/chardet/mbcharsetprober.py | 91 - .../pip/_vendor/chardet/mbcsgroupprober.py | 54 - .../pip/_vendor/chardet/mbcssm.py | 572 -- .../pip/_vendor/chardet/sbcharsetprober.py | 132 - .../pip/_vendor/chardet/sbcsgroupprober.py | 73 - .../pip/_vendor/chardet/sjisprober.py | 92 - .../pip/_vendor/chardet/universaldetector.py | 286 - .../pip/_vendor/chardet/utf8prober.py | 82 - .../pip/_vendor/chardet/version.py | 9 - .../pip/_vendor/colorama/__init__.py | 6 - .../__pycache__/__init__.cpython-37.pyc | Bin 400 -> 0 bytes .../colorama/__pycache__/ansi.cpython-37.pyc | Bin 3298 -> 0 bytes .../__pycache__/ansitowin32.cpython-37.pyc | Bin 7554 -> 0 bytes .../__pycache__/initialise.cpython-37.pyc | Bin 1619 -> 0 bytes .../colorama/__pycache__/win32.cpython-37.pyc | Bin 3813 -> 0 bytes .../__pycache__/winterm.cpython-37.pyc | Bin 4561 -> 0 bytes .../pip/_vendor/colorama/ansi.py | 102 - .../pip/_vendor/colorama/ansitowin32.py | 257 - .../pip/_vendor/colorama/initialise.py | 80 - .../pip/_vendor/colorama/win32.py | 152 - .../pip/_vendor/colorama/winterm.py | 169 - .../site-packages/pip/_vendor/contextlib2.py | 518 -- .../pip/_vendor/distlib/__init__.py | 23 - .../__pycache__/__init__.cpython-37.pyc | Bin 998 -> 0 bytes .../distlib/__pycache__/compat.cpython-37.pyc | Bin 32008 -> 0 bytes .../__pycache__/database.cpython-37.pyc | Bin 42547 -> 0 bytes .../distlib/__pycache__/index.cpython-37.pyc | Bin 17287 -> 0 bytes .../__pycache__/locators.cpython-37.pyc | Bin 38765 -> 0 bytes .../__pycache__/manifest.cpython-37.pyc | Bin 10246 -> 0 bytes .../__pycache__/markers.cpython-37.pyc | Bin 4432 -> 0 bytes .../__pycache__/metadata.cpython-37.pyc | Bin 27647 -> 0 bytes .../__pycache__/resources.cpython-37.pyc | Bin 10842 -> 0 bytes .../__pycache__/scripts.cpython-37.pyc | Bin 10721 -> 0 bytes .../distlib/__pycache__/util.cpython-37.pyc | Bin 47975 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 20382 -> 0 bytes .../distlib/__pycache__/wheel.cpython-37.pyc | Bin 25583 -> 0 bytes .../pip/_vendor/distlib/_backport/__init__.py | 6 - .../__pycache__/__init__.cpython-37.pyc | Bin 440 -> 0 bytes .../_backport/__pycache__/misc.cpython-37.pyc | Bin 1037 -> 0 bytes .../__pycache__/shutil.cpython-37.pyc | Bin 21353 -> 0 bytes .../__pycache__/sysconfig.cpython-37.pyc | Bin 15846 -> 0 bytes .../__pycache__/tarfile.cpython-37.pyc | Bin 62683 -> 0 bytes .../pip/_vendor/distlib/_backport/misc.py | 41 - .../pip/_vendor/distlib/_backport/shutil.py | 761 -- .../_vendor/distlib/_backport/sysconfig.cfg | 84 - .../_vendor/distlib/_backport/sysconfig.py | 786 -- .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ------ .../pip/_vendor/distlib/compat.py | 1120 --- .../pip/_vendor/distlib/database.py | 1339 --- .../pip/_vendor/distlib/index.py | 516 -- .../pip/_vendor/distlib/locators.py | 1302 --- .../pip/_vendor/distlib/manifest.py | 393 - .../pip/_vendor/distlib/markers.py | 131 - .../pip/_vendor/distlib/metadata.py | 1096 --- .../pip/_vendor/distlib/resources.py | 355 - .../pip/_vendor/distlib/scripts.py | 416 - .../site-packages/pip/_vendor/distlib/t32.exe | Bin 96768 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 105984 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1761 ---- .../pip/_vendor/distlib/version.py | 736 -- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 90112 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 99840 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 1004 -- .../site-packages/pip/_vendor/distro.py | 1216 --- .../pip/_vendor/html5lib/__init__.py | 35 - .../__pycache__/__init__.cpython-37.pyc | Bin 1269 -> 0 bytes .../__pycache__/_ihatexml.cpython-37.pyc | Bin 13716 -> 0 bytes .../__pycache__/_inputstream.cpython-37.pyc | Bin 22607 -> 0 bytes .../__pycache__/_tokenizer.cpython-37.pyc | Bin 41508 -> 0 bytes .../__pycache__/_utils.cpython-37.pyc | Bin 3261 -> 0 bytes .../__pycache__/constants.cpython-37.pyc | Bin 66173 -> 0 bytes .../__pycache__/html5parser.cpython-37.pyc | Bin 97770 -> 0 bytes .../__pycache__/serializer.cpython-37.pyc | Bin 10786 -> 0 bytes .../pip/_vendor/html5lib/_ihatexml.py | 288 - .../pip/_vendor/html5lib/_inputstream.py | 923 -- .../pip/_vendor/html5lib/_tokenizer.py | 1721 ---- .../pip/_vendor/html5lib/_trie/__init__.py | 14 - .../_trie/__pycache__/__init__.cpython-37.pyc | Bin 382 -> 0 bytes .../_trie/__pycache__/_base.cpython-37.pyc | Bin 1539 -> 0 bytes .../_trie/__pycache__/datrie.cpython-37.pyc | Bin 1984 -> 0 bytes .../_trie/__pycache__/py.cpython-37.pyc | Bin 2187 -> 0 bytes .../pip/_vendor/html5lib/_trie/_base.py | 40 - .../pip/_vendor/html5lib/_trie/datrie.py | 44 - .../pip/_vendor/html5lib/_trie/py.py | 67 - .../pip/_vendor/html5lib/_utils.py | 124 - .../pip/_vendor/html5lib/constants.py | 2947 ------ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 157 -> 0 bytes .../alphabeticalattributes.cpython-37.pyc | Bin 1273 -> 0 bytes .../filters/__pycache__/base.cpython-37.pyc | Bin 807 -> 0 bytes .../inject_meta_charset.cpython-37.pyc | Bin 1827 -> 0 bytes .../filters/__pycache__/lint.cpython-37.pyc | Bin 2591 -> 0 bytes .../__pycache__/optionaltags.cpython-37.pyc | Bin 2718 -> 0 bytes .../__pycache__/sanitizer.cpython-37.pyc | Bin 16393 -> 0 bytes .../__pycache__/whitespace.cpython-37.pyc | Bin 1311 -> 0 bytes .../filters/alphabeticalattributes.py | 29 - .../pip/_vendor/html5lib/filters/base.py | 12 - .../html5lib/filters/inject_meta_charset.py | 73 - .../pip/_vendor/html5lib/filters/lint.py | 93 - .../_vendor/html5lib/filters/optionaltags.py | 207 - .../pip/_vendor/html5lib/filters/sanitizer.py | 896 -- .../_vendor/html5lib/filters/whitespace.py | 38 - .../pip/_vendor/html5lib/html5parser.py | 2791 ------ .../pip/_vendor/html5lib/serializer.py | 409 - .../_vendor/html5lib/treeadapters/__init__.py | 30 - .../__pycache__/__init__.cpython-37.pyc | Bin 896 -> 0 bytes .../__pycache__/genshi.cpython-37.pyc | Bin 1493 -> 0 bytes .../__pycache__/sax.cpython-37.pyc | Bin 1443 -> 0 bytes .../_vendor/html5lib/treeadapters/genshi.py | 54 - .../pip/_vendor/html5lib/treeadapters/sax.py | 50 - .../_vendor/html5lib/treebuilders/__init__.py | 88 - .../__pycache__/__init__.cpython-37.pyc | Bin 3277 -> 0 bytes .../__pycache__/base.cpython-37.pyc | Bin 11200 -> 0 bytes .../__pycache__/dom.cpython-37.pyc | Bin 9304 -> 0 bytes .../__pycache__/etree.cpython-37.pyc | Bin 11809 -> 0 bytes .../__pycache__/etree_lxml.cpython-37.pyc | Bin 11749 -> 0 bytes .../pip/_vendor/html5lib/treebuilders/base.py | 417 - .../pip/_vendor/html5lib/treebuilders/dom.py | 239 - .../_vendor/html5lib/treebuilders/etree.py | 340 - .../html5lib/treebuilders/etree_lxml.py | 366 - .../_vendor/html5lib/treewalkers/__init__.py | 154 - .../__pycache__/__init__.cpython-37.pyc | Bin 3954 -> 0 bytes .../__pycache__/base.cpython-37.pyc | Bin 6950 -> 0 bytes .../__pycache__/dom.cpython-37.pyc | Bin 1679 -> 0 bytes .../__pycache__/etree.cpython-37.pyc | Bin 3486 -> 0 bytes .../__pycache__/etree_lxml.cpython-37.pyc | Bin 6595 -> 0 bytes .../__pycache__/genshi.cpython-37.pyc | Bin 1853 -> 0 bytes .../pip/_vendor/html5lib/treewalkers/base.py | 252 - .../pip/_vendor/html5lib/treewalkers/dom.py | 43 - .../pip/_vendor/html5lib/treewalkers/etree.py | 130 - .../html5lib/treewalkers/etree_lxml.py | 213 - .../_vendor/html5lib/treewalkers/genshi.py | 69 - .../pip/_vendor/idna/__init__.py | 2 - .../idna/__pycache__/__init__.cpython-37.pyc | Bin 214 -> 0 bytes .../idna/__pycache__/codec.cpython-37.pyc | Bin 3021 -> 0 bytes .../idna/__pycache__/compat.cpython-37.pyc | Bin 574 -> 0 bytes .../idna/__pycache__/core.cpython-37.pyc | Bin 9017 -> 0 bytes .../idna/__pycache__/idnadata.cpython-37.pyc | Bin 21388 -> 0 bytes .../idna/__pycache__/intranges.cpython-37.pyc | Bin 1754 -> 0 bytes .../__pycache__/package_data.cpython-37.pyc | Bin 168 -> 0 bytes .../idna/__pycache__/uts46data.cpython-37.pyc | Bin 176048 -> 0 bytes .../site-packages/pip/_vendor/idna/codec.py | 118 - .../site-packages/pip/_vendor/idna/compat.py | 12 - .../site-packages/pip/_vendor/idna/core.py | 396 - .../pip/_vendor/idna/idnadata.py | 1979 ---- .../pip/_vendor/idna/intranges.py | 53 - .../pip/_vendor/idna/package_data.py | 2 - .../pip/_vendor/idna/uts46data.py | 8205 ----------------- .../site-packages/pip/_vendor/ipaddress.py | 2420 ----- .../pip/_vendor/msgpack/__init__.py | 65 - .../__pycache__/__init__.cpython-37.pyc | Bin 1893 -> 0 bytes .../__pycache__/_version.cpython-37.pyc | Bin 175 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 1823 -> 0 bytes .../__pycache__/fallback.cpython-37.pyc | Bin 26227 -> 0 bytes .../pip/_vendor/msgpack/_version.py | 1 - .../pip/_vendor/msgpack/exceptions.py | 48 - .../pip/_vendor/msgpack/fallback.py | 1027 --- .../pip/_vendor/packaging/__about__.py | 27 - .../pip/_vendor/packaging/__init__.py | 26 - .../__pycache__/__about__.cpython-37.pyc | Bin 688 -> 0 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 526 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 1107 -> 0 bytes .../__pycache__/_structures.cpython-37.pyc | Bin 2926 -> 0 bytes .../__pycache__/_typing.cpython-37.pyc | Bin 1441 -> 0 bytes .../__pycache__/markers.cpython-37.pyc | Bin 9231 -> 0 bytes .../__pycache__/requirements.cpython-37.pyc | Bin 4030 -> 0 bytes .../__pycache__/specifiers.cpython-37.pyc | Bin 20241 -> 0 bytes .../packaging/__pycache__/tags.cpython-37.pyc | Bin 16382 -> 0 bytes .../__pycache__/utils.cpython-37.pyc | Bin 1505 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 13105 -> 0 bytes .../pip/_vendor/packaging/_compat.py | 38 - .../pip/_vendor/packaging/_structures.py | 86 - .../pip/_vendor/packaging/_typing.py | 39 - .../pip/_vendor/packaging/markers.py | 328 - .../pip/_vendor/packaging/requirements.py | 145 - .../pip/_vendor/packaging/specifiers.py | 849 -- .../pip/_vendor/packaging/tags.py | 730 -- .../pip/_vendor/packaging/utils.py | 62 - .../pip/_vendor/packaging/version.py | 535 -- .../pip/_vendor/pep517/__init__.py | 4 - .../__pycache__/__init__.cpython-37.pyc | Bin 239 -> 0 bytes .../__pycache__/_in_process.cpython-37.pyc | Bin 7509 -> 0 bytes .../pep517/__pycache__/build.cpython-37.pyc | Bin 3302 -> 0 bytes .../pep517/__pycache__/check.cpython-37.pyc | Bin 4804 -> 0 bytes .../__pycache__/colorlog.cpython-37.pyc | Bin 2871 -> 0 bytes .../pep517/__pycache__/compat.cpython-37.pyc | Bin 1020 -> 0 bytes .../__pycache__/dirtools.cpython-37.pyc | Bin 1284 -> 0 bytes .../__pycache__/envbuild.cpython-37.pyc | Bin 4293 -> 0 bytes .../pep517/__pycache__/meta.cpython-37.pyc | Bin 2771 -> 0 bytes .../__pycache__/wrappers.cpython-37.pyc | Bin 10067 -> 0 bytes .../pip/_vendor/pep517/_in_process.py | 257 - .../site-packages/pip/_vendor/pep517/build.py | 124 - .../site-packages/pip/_vendor/pep517/check.py | 203 - .../pip/_vendor/pep517/colorlog.py | 115 - .../pip/_vendor/pep517/compat.py | 34 - .../pip/_vendor/pep517/dirtools.py | 44 - .../pip/_vendor/pep517/envbuild.py | 167 - .../site-packages/pip/_vendor/pep517/meta.py | 92 - .../pip/_vendor/pep517/wrappers.py | 298 - .../pip/_vendor/pkg_resources/__init__.py | 3296 ------- .../__pycache__/__init__.cpython-37.pyc | Bin 99699 -> 0 bytes .../__pycache__/py31compat.cpython-37.pyc | Bin 599 -> 0 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 - .../pip/_vendor/progress/__init__.py | 177 - .../__pycache__/__init__.cpython-37.pyc | Bin 5515 -> 0 bytes .../progress/__pycache__/bar.cpython-37.pyc | Bin 2607 -> 0 bytes .../__pycache__/counter.cpython-37.pyc | Bin 1419 -> 0 bytes .../__pycache__/spinner.cpython-37.pyc | Bin 1384 -> 0 bytes .../site-packages/pip/_vendor/progress/bar.py | 91 - .../pip/_vendor/progress/counter.py | 41 - .../pip/_vendor/progress/spinner.py | 43 - .../site-packages/pip/_vendor/pyparsing.py | 7090 -------------- .../pip/_vendor/pytoml/__init__.py | 4 - .../__pycache__/__init__.cpython-37.pyc | Bin 333 -> 0 bytes .../pytoml/__pycache__/core.cpython-37.pyc | Bin 896 -> 0 bytes .../pytoml/__pycache__/parser.cpython-37.pyc | Bin 9981 -> 0 bytes .../pytoml/__pycache__/test.cpython-37.pyc | Bin 1196 -> 0 bytes .../pytoml/__pycache__/utils.cpython-37.pyc | Bin 2095 -> 0 bytes .../pytoml/__pycache__/writer.cpython-37.pyc | Bin 3675 -> 0 bytes .../site-packages/pip/_vendor/pytoml/core.py | 13 - .../pip/_vendor/pytoml/parser.py | 342 - .../site-packages/pip/_vendor/pytoml/test.py | 30 - .../site-packages/pip/_vendor/pytoml/utils.py | 67 - .../pip/_vendor/pytoml/writer.py | 114 - .../pip/_vendor/requests/__init__.py | 133 - .../__pycache__/__init__.cpython-37.pyc | Bin 3444 -> 0 bytes .../__pycache__/__version__.cpython-37.pyc | Bin 507 -> 0 bytes .../_internal_utils.cpython-37.pyc | Bin 1265 -> 0 bytes .../__pycache__/adapters.cpython-37.pyc | Bin 16842 -> 0 bytes .../requests/__pycache__/api.cpython-37.pyc | Bin 6466 -> 0 bytes .../requests/__pycache__/auth.cpython-37.pyc | Bin 8299 -> 0 bytes .../requests/__pycache__/certs.cpython-37.pyc | Bin 590 -> 0 bytes .../__pycache__/compat.cpython-37.pyc | Bin 1569 -> 0 bytes .../__pycache__/cookies.cpython-37.pyc | Bin 18744 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 5462 -> 0 bytes .../requests/__pycache__/help.cpython-37.pyc | Bin 2643 -> 0 bytes .../requests/__pycache__/hooks.cpython-37.pyc | Bin 937 -> 0 bytes .../__pycache__/models.cpython-37.pyc | Bin 24065 -> 0 bytes .../__pycache__/packages.cpython-37.pyc | Bin 467 -> 0 bytes .../__pycache__/sessions.cpython-37.pyc | Bin 19385 -> 0 bytes .../__pycache__/status_codes.cpython-37.pyc | Bin 4123 -> 0 bytes .../__pycache__/structures.cpython-37.pyc | Bin 4336 -> 0 bytes .../requests/__pycache__/utils.cpython-37.pyc | Bin 21996 -> 0 bytes .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 42 - .../pip/_vendor/requests/adapters.py | 533 -- .../site-packages/pip/_vendor/requests/api.py | 158 - .../pip/_vendor/requests/auth.py | 305 - .../pip/_vendor/requests/certs.py | 18 - .../pip/_vendor/requests/compat.py | 74 - .../pip/_vendor/requests/cookies.py | 549 -- .../pip/_vendor/requests/exceptions.py | 126 - .../pip/_vendor/requests/help.py | 119 - .../pip/_vendor/requests/hooks.py | 34 - .../pip/_vendor/requests/models.py | 953 -- .../pip/_vendor/requests/packages.py | 16 - .../pip/_vendor/requests/sessions.py | 770 -- .../pip/_vendor/requests/status_codes.py | 120 - .../pip/_vendor/requests/structures.py | 103 - .../pip/_vendor/requests/utils.py | 977 -- .../site-packages/pip/_vendor/retrying.py | 267 - .../site-packages/pip/_vendor/six.py | 980 -- .../pip/_vendor/urllib3/__init__.py | 86 - .../__pycache__/__init__.cpython-37.pyc | Bin 2070 -> 0 bytes .../__pycache__/_collections.cpython-37.pyc | Bin 10640 -> 0 bytes .../__pycache__/connection.cpython-37.pyc | Bin 10424 -> 0 bytes .../__pycache__/connectionpool.cpython-37.pyc | Bin 24028 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 10357 -> 0 bytes .../urllib3/__pycache__/fields.cpython-37.pyc | Bin 8051 -> 0 bytes .../__pycache__/filepost.cpython-37.pyc | Bin 2717 -> 0 bytes .../__pycache__/poolmanager.cpython-37.pyc | Bin 12813 -> 0 bytes .../__pycache__/request.cpython-37.pyc | Bin 5549 -> 0 bytes .../__pycache__/response.cpython-37.pyc | Bin 20148 -> 0 bytes .../pip/_vendor/urllib3/_collections.py | 336 - .../pip/_vendor/urllib3/connection.py | 448 - .../pip/_vendor/urllib3/connectionpool.py | 1051 --- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 156 -> 0 bytes .../_appengine_environ.cpython-37.pyc | Bin 1356 -> 0 bytes .../__pycache__/appengine.cpython-37.pyc | Bin 8137 -> 0 bytes .../__pycache__/ntlmpool.cpython-37.pyc | Bin 3202 -> 0 bytes .../__pycache__/pyopenssl.cpython-37.pyc | Bin 14767 -> 0 bytes .../securetransport.cpython-37.pyc | Bin 19645 -> 0 bytes .../contrib/__pycache__/socks.cpython-37.pyc | Bin 5472 -> 0 bytes .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 173 -> 0 bytes .../__pycache__/bindings.cpython-37.pyc | Bin 10120 -> 0 bytes .../__pycache__/low_level.cpython-37.pyc | Bin 7417 -> 0 bytes .../contrib/_securetransport/bindings.py | 493 - .../contrib/_securetransport/low_level.py | 328 - .../pip/_vendor/urllib3/contrib/appengine.py | 314 - .../pip/_vendor/urllib3/contrib/ntlmpool.py | 121 - .../pip/_vendor/urllib3/contrib/pyopenssl.py | 498 - .../urllib3/contrib/securetransport.py | 859 -- .../pip/_vendor/urllib3/contrib/socks.py | 210 - .../pip/_vendor/urllib3/exceptions.py | 255 - .../pip/_vendor/urllib3/fields.py | 273 - .../pip/_vendor/urllib3/filepost.py | 98 - .../pip/_vendor/urllib3/packages/__init__.py | 5 - .../__pycache__/__init__.cpython-37.pyc | Bin 270 -> 0 bytes .../packages/__pycache__/six.cpython-37.pyc | Bin 26413 -> 0 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 167 -> 0 bytes .../__pycache__/makefile.cpython-37.pyc | Bin 1257 -> 0 bytes .../urllib3/packages/backports/makefile.py | 52 - .../pip/_vendor/urllib3/packages/six.py | 1021 -- .../packages/ssl_match_hostname/__init__.py | 19 - .../__pycache__/__init__.cpython-37.pyc | Bin 511 -> 0 bytes .../_implementation.cpython-37.pyc | Bin 3274 -> 0 bytes .../ssl_match_hostname/_implementation.py | 160 - .../pip/_vendor/urllib3/poolmanager.py | 470 - .../pip/_vendor/urllib3/request.py | 171 - .../pip/_vendor/urllib3/response.py | 809 -- .../pip/_vendor/urllib3/util/__init__.py | 46 - .../util/__pycache__/__init__.cpython-37.pyc | Bin 976 -> 0 bytes .../__pycache__/connection.cpython-37.pyc | Bin 3125 -> 0 bytes .../util/__pycache__/queue.cpython-37.pyc | Bin 997 -> 0 bytes .../util/__pycache__/request.cpython-37.pyc | Bin 3291 -> 0 bytes .../util/__pycache__/response.cpython-37.pyc | Bin 1924 -> 0 bytes .../util/__pycache__/retry.cpython-37.pyc | Bin 12845 -> 0 bytes .../util/__pycache__/ssl_.cpython-37.pyc | Bin 9718 -> 0 bytes .../util/__pycache__/timeout.cpython-37.pyc | Bin 8784 -> 0 bytes .../util/__pycache__/url.cpython-37.pyc | Bin 10513 -> 0 bytes .../util/__pycache__/wait.cpython-37.pyc | Bin 3089 -> 0 bytes .../pip/_vendor/urllib3/util/connection.py | 138 - .../pip/_vendor/urllib3/util/queue.py | 21 - .../pip/_vendor/urllib3/util/request.py | 135 - .../pip/_vendor/urllib3/util/response.py | 86 - .../pip/_vendor/urllib3/util/retry.py | 450 - .../pip/_vendor/urllib3/util/ssl_.py | 407 - .../pip/_vendor/urllib3/util/timeout.py | 258 - .../pip/_vendor/urllib3/util/url.py | 436 - .../pip/_vendor/urllib3/util/wait.py | 153 - .../pip/_vendor/webencodings/__init__.py | 342 - .../__pycache__/__init__.cpython-37.pyc | Bin 9632 -> 0 bytes .../__pycache__/labels.cpython-37.pyc | Bin 4046 -> 0 bytes .../__pycache__/mklabels.cpython-37.pyc | Bin 1868 -> 0 bytes .../__pycache__/tests.cpython-37.pyc | Bin 5009 -> 0 bytes .../__pycache__/x_user_defined.cpython-37.pyc | Bin 2621 -> 0 bytes .../pip/_vendor/webencodings/labels.py | 231 - .../pip/_vendor/webencodings/mklabels.py | 59 - .../pip/_vendor/webencodings/tests.py | 153 - .../_vendor/webencodings/x_user_defined.py | 325 - .../site-packages/pkg_resources/__init__.py | 3304 ------- .../__pycache__/__init__.cpython-37.pyc | Bin 99891 -> 0 bytes .../__pycache__/py2_warn.cpython-37.pyc | Bin 865 -> 0 bytes .../__pycache__/py31compat.cpython-37.pyc | Bin 594 -> 0 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 157 -> 0 bytes .../__pycache__/appdirs.cpython-37.pyc | Bin 20645 -> 0 bytes .../__pycache__/pyparsing.cpython-37.pyc | Bin 203000 -> 0 bytes .../_vendor/__pycache__/six.cpython-37.pyc | Bin 24358 -> 0 bytes .../pkg_resources/_vendor/appdirs.py | 608 -- .../_vendor/packaging/__about__.py | 21 - .../_vendor/packaging/__init__.py | 14 - .../__pycache__/__about__.cpython-37.pyc | Bin 693 -> 0 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 531 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 983 -> 0 bytes .../__pycache__/_structures.cpython-37.pyc | Bin 2835 -> 0 bytes .../__pycache__/markers.cpython-37.pyc | Bin 8843 -> 0 bytes .../__pycache__/requirements.cpython-37.pyc | Bin 3848 -> 0 bytes .../__pycache__/specifiers.cpython-37.pyc | Bin 19761 -> 0 bytes .../__pycache__/utils.cpython-37.pyc | Bin 462 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 10528 -> 0 bytes .../_vendor/packaging/_compat.py | 30 - .../_vendor/packaging/_structures.py | 68 - .../_vendor/packaging/markers.py | 301 - .../_vendor/packaging/requirements.py | 127 - .../_vendor/packaging/specifiers.py | 774 -- .../pkg_resources/_vendor/packaging/utils.py | 14 - .../_vendor/packaging/version.py | 393 - .../pkg_resources/_vendor/pyparsing.py | 5742 ------------ .../pkg_resources/_vendor/six.py | 868 -- .../pkg_resources/extern/__init__.py | 66 - .../__pycache__/__init__.cpython-37.pyc | Bin 2324 -> 0 bytes .../site-packages/pkg_resources/py2_warn.py | 21 - .../site-packages/pkg_resources/py31compat.py | 23 - .../setuptools-46.1.3.dist-info/INSTALLER | 1 - .../setuptools-46.1.3.dist-info/LICENSE | 19 - .../setuptools-46.1.3.dist-info/METADATA | 108 - .../setuptools-46.1.3.dist-info/RECORD | 196 - .../setuptools-46.1.3.dist-info/WHEEL | 5 - .../dependency_links.txt | 2 - .../entry_points.txt | 68 - .../setuptools-46.1.3.dist-info/top_level.txt | 3 - .../setuptools-46.1.3.dist-info/zip-safe | 1 - .../site-packages/setuptools/__init__.py | 232 - .../__pycache__/__init__.cpython-37.pyc | Bin 7820 -> 0 bytes .../_deprecation_warning.cpython-37.pyc | Bin 512 -> 0 bytes .../__pycache__/_imp.cpython-37.pyc | Bin 2050 -> 0 bytes .../__pycache__/archive_util.cpython-37.pyc | Bin 5095 -> 0 bytes .../__pycache__/build_meta.cpython-37.pyc | Bin 8500 -> 0 bytes .../__pycache__/config.cpython-37.pyc | Bin 17775 -> 0 bytes .../__pycache__/dep_util.cpython-37.pyc | Bin 821 -> 0 bytes .../__pycache__/depends.cpython-37.pyc | Bin 5138 -> 0 bytes .../__pycache__/dist.cpython-37.pyc | Bin 32923 -> 0 bytes .../__pycache__/errors.cpython-37.pyc | Bin 812 -> 0 bytes .../__pycache__/extension.cpython-37.pyc | Bin 1939 -> 0 bytes .../__pycache__/glob.cpython-37.pyc | Bin 3714 -> 0 bytes .../__pycache__/installer.cpython-37.pyc | Bin 4032 -> 0 bytes .../__pycache__/launch.cpython-37.pyc | Bin 818 -> 0 bytes .../__pycache__/lib2to3_ex.cpython-37.pyc | Bin 2397 -> 0 bytes .../__pycache__/monkey.cpython-37.pyc | Bin 4598 -> 0 bytes .../__pycache__/msvc.cpython-37.pyc | Bin 42981 -> 0 bytes .../__pycache__/namespaces.cpython-37.pyc | Bin 3576 -> 0 bytes .../__pycache__/package_index.cpython-37.pyc | Bin 32762 -> 0 bytes .../__pycache__/py27compat.cpython-37.pyc | Bin 1728 -> 0 bytes .../__pycache__/py31compat.cpython-37.pyc | Bin 1173 -> 0 bytes .../__pycache__/py33compat.cpython-37.pyc | Bin 1400 -> 0 bytes .../__pycache__/py34compat.cpython-37.pyc | Bin 446 -> 0 bytes .../__pycache__/sandbox.cpython-37.pyc | Bin 15502 -> 0 bytes .../__pycache__/site-patch.cpython-37.pyc | Bin 1468 -> 0 bytes .../__pycache__/ssl_support.cpython-37.pyc | Bin 6766 -> 0 bytes .../__pycache__/unicode_utils.cpython-37.pyc | Bin 1133 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 292 -> 0 bytes .../__pycache__/wheel.cpython-37.pyc | Bin 7275 -> 0 bytes .../windows_support.cpython-37.pyc | Bin 975 -> 0 bytes .../setuptools/_deprecation_warning.py | 7 - .../site-packages/setuptools/_imp.py | 82 - .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 154 -> 0 bytes .../__pycache__/ordered_set.cpython-37.pyc | Bin 16374 -> 0 bytes .../__pycache__/pyparsing.cpython-37.pyc | Bin 202997 -> 0 bytes .../_vendor/__pycache__/six.cpython-37.pyc | Bin 24355 -> 0 bytes .../setuptools/_vendor/ordered_set.py | 488 - .../setuptools/_vendor/packaging/__about__.py | 27 - .../setuptools/_vendor/packaging/__init__.py | 26 - .../__pycache__/__about__.cpython-37.pyc | Bin 702 -> 0 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 540 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 980 -> 0 bytes .../__pycache__/_structures.cpython-37.pyc | Bin 2832 -> 0 bytes .../__pycache__/markers.cpython-37.pyc | Bin 8877 -> 0 bytes .../__pycache__/requirements.cpython-37.pyc | Bin 3965 -> 0 bytes .../__pycache__/specifiers.cpython-37.pyc | Bin 19730 -> 0 bytes .../packaging/__pycache__/tags.cpython-37.pyc | Bin 10779 -> 0 bytes .../__pycache__/utils.cpython-37.pyc | Bin 1418 -> 0 bytes .../__pycache__/version.cpython-37.pyc | Bin 11922 -> 0 bytes .../setuptools/_vendor/packaging/_compat.py | 31 - .../_vendor/packaging/_structures.py | 68 - .../setuptools/_vendor/packaging/markers.py | 296 - .../_vendor/packaging/requirements.py | 138 - .../_vendor/packaging/specifiers.py | 749 -- .../setuptools/_vendor/packaging/tags.py | 404 - .../setuptools/_vendor/packaging/utils.py | 57 - .../setuptools/_vendor/packaging/version.py | 420 - .../setuptools/_vendor/pyparsing.py | 5742 ------------ .../site-packages/setuptools/_vendor/six.py | 868 -- .../site-packages/setuptools/archive_util.py | 175 - .../site-packages/setuptools/build_meta.py | 272 - .../site-packages/setuptools/cli-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../site-packages/setuptools/cli.exe | Bin 65536 -> 0 bytes .../setuptools/command/__init__.py | 17 - .../__pycache__/__init__.cpython-37.pyc | Bin 676 -> 0 bytes .../command/__pycache__/alias.cpython-37.pyc | Bin 2368 -> 0 bytes .../__pycache__/bdist_egg.cpython-37.pyc | Bin 14323 -> 0 bytes .../__pycache__/bdist_rpm.cpython-37.pyc | Bin 1747 -> 0 bytes .../__pycache__/bdist_wininst.cpython-37.pyc | Bin 938 -> 0 bytes .../__pycache__/build_clib.cpython-37.pyc | Bin 2410 -> 0 bytes .../__pycache__/build_ext.cpython-37.pyc | Bin 9719 -> 0 bytes .../__pycache__/build_py.cpython-37.pyc | Bin 8743 -> 0 bytes .../__pycache__/develop.cpython-37.pyc | Bin 6428 -> 0 bytes .../__pycache__/dist_info.cpython-37.pyc | Bin 1343 -> 0 bytes .../__pycache__/easy_install.cpython-37.pyc | Bin 64892 -> 0 bytes .../__pycache__/egg_info.cpython-37.pyc | Bin 21595 -> 0 bytes .../__pycache__/install.cpython-37.pyc | Bin 4000 -> 0 bytes .../install_egg_info.cpython-37.pyc | Bin 2376 -> 0 bytes .../__pycache__/install_lib.cpython-37.pyc | Bin 4072 -> 0 bytes .../install_scripts.cpython-37.pyc | Bin 2306 -> 0 bytes .../__pycache__/py36compat.cpython-37.pyc | Bin 4588 -> 0 bytes .../__pycache__/register.cpython-37.pyc | Bin 801 -> 0 bytes .../command/__pycache__/rotate.cpython-37.pyc | Bin 2494 -> 0 bytes .../__pycache__/saveopts.cpython-37.pyc | Bin 889 -> 0 bytes .../command/__pycache__/sdist.cpython-37.pyc | Bin 7794 -> 0 bytes .../command/__pycache__/setopt.cpython-37.pyc | Bin 4487 -> 0 bytes .../command/__pycache__/test.cpython-37.pyc | Bin 8377 -> 0 bytes .../command/__pycache__/upload.cpython-37.pyc | Bin 774 -> 0 bytes .../__pycache__/upload_docs.cpython-37.pyc | Bin 6095 -> 0 bytes .../site-packages/setuptools/command/alias.py | 80 - .../setuptools/command/bdist_egg.py | 509 - .../setuptools/command/bdist_rpm.py | 43 - .../setuptools/command/bdist_wininst.py | 21 - .../setuptools/command/build_clib.py | 101 - .../setuptools/command/build_ext.py | 330 - .../setuptools/command/build_py.py | 276 - .../setuptools/command/develop.py | 221 - .../setuptools/command/dist_info.py | 36 - .../setuptools/command/easy_install.py | 2355 ----- .../setuptools/command/egg_info.py | 721 -- .../setuptools/command/install.py | 125 - .../setuptools/command/install_egg_info.py | 62 - .../setuptools/command/install_lib.py | 122 - .../setuptools/command/install_scripts.py | 68 - .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/py36compat.py | 136 - .../setuptools/command/register.py | 18 - .../setuptools/command/rotate.py | 66 - .../setuptools/command/saveopts.py | 22 - .../site-packages/setuptools/command/sdist.py | 252 - .../setuptools/command/setopt.py | 149 - .../site-packages/setuptools/command/test.py | 280 - .../setuptools/command/upload.py | 17 - .../setuptools/command/upload_docs.py | 206 - .../site-packages/setuptools/config.py | 659 -- .../site-packages/setuptools/dep_util.py | 25 - .../site-packages/setuptools/depends.py | 176 - .../site-packages/setuptools/dist.py | 1031 --- .../site-packages/setuptools/errors.py | 16 - .../site-packages/setuptools/extension.py | 57 - .../setuptools/extern/__init__.py | 66 - .../__pycache__/__init__.cpython-37.pyc | Bin 2347 -> 0 bytes .../site-packages/setuptools/glob.py | 174 - .../site-packages/setuptools/gui-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../site-packages/setuptools/gui.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/installer.py | 150 - .../site-packages/setuptools/launch.py | 35 - .../site-packages/setuptools/lib2to3_ex.py | 62 - .../site-packages/setuptools/monkey.py | 179 - .../site-packages/setuptools/msvc.py | 1825 ---- .../site-packages/setuptools/namespaces.py | 111 - .../site-packages/setuptools/package_index.py | 1140 --- .../site-packages/setuptools/py27compat.py | 60 - .../site-packages/setuptools/py31compat.py | 32 - .../site-packages/setuptools/py33compat.py | 59 - .../site-packages/setuptools/py34compat.py | 13 - .../site-packages/setuptools/sandbox.py | 492 - .../setuptools/script (dev).tmpl | 6 - .../site-packages/setuptools/script.tmpl | 3 - .../site-packages/setuptools/site-patch.py | 76 - .../site-packages/setuptools/ssl_support.py | 265 - .../site-packages/setuptools/unicode_utils.py | 44 - .../site-packages/setuptools/version.py | 6 - .../site-packages/setuptools/wheel.py | 221 - .../setuptools/windows_support.py | 29 - .../six-1.14.0.dist-info/INSTALLER | 1 - .../six-1.14.0.dist-info/LICENSE | 18 - .../six-1.14.0.dist-info/METADATA | 49 - .../site-packages/six-1.14.0.dist-info/RECORD | 8 - .../site-packages/six-1.14.0.dist-info/WHEEL | 6 - .../six-1.14.0.dist-info/top_level.txt | 1 - .../venv/lib/python3.7/site-packages/six.py | 980 -- .../site-packages/werkzeug/__init__.py | 20 - .../__pycache__/__init__.cpython-37.pyc | Bin 688 -> 0 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 7343 -> 0 bytes .../__pycache__/_internal.cpython-37.pyc | Bin 13075 -> 0 bytes .../__pycache__/_reloader.cpython-37.pyc | Bin 9594 -> 0 bytes .../__pycache__/datastructures.cpython-37.pyc | Bin 109452 -> 0 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 27631 -> 0 bytes .../__pycache__/filesystem.cpython-37.pyc | Bin 2127 -> 0 bytes .../__pycache__/formparser.cpython-37.pyc | Bin 16072 -> 0 bytes .../werkzeug/__pycache__/http.cpython-37.pyc | Bin 35452 -> 0 bytes .../werkzeug/__pycache__/local.cpython-37.pyc | Bin 18493 -> 0 bytes .../__pycache__/posixemulation.cpython-37.pyc | Bin 2699 -> 0 bytes .../__pycache__/routing.cpython-37.pyc | Bin 67770 -> 0 bytes .../__pycache__/security.cpython-37.pyc | Bin 7900 -> 0 bytes .../__pycache__/serving.cpython-37.pyc | Bin 29385 -> 0 bytes .../werkzeug/__pycache__/test.cpython-37.pyc | Bin 32842 -> 0 bytes .../__pycache__/testapp.cpython-37.pyc | Bin 9338 -> 0 bytes .../werkzeug/__pycache__/urls.cpython-37.pyc | Bin 35797 -> 0 bytes .../__pycache__/useragents.cpython-37.pyc | Bin 5435 -> 0 bytes .../werkzeug/__pycache__/utils.cpython-37.pyc | Bin 22896 -> 0 bytes .../werkzeug/__pycache__/wsgi.cpython-37.pyc | Bin 30805 -> 0 bytes .../site-packages/werkzeug/_compat.py | 228 - .../site-packages/werkzeug/_internal.py | 473 - .../site-packages/werkzeug/_reloader.py | 341 - .../site-packages/werkzeug/datastructures.py | 3120 ------- .../site-packages/werkzeug/debug/__init__.py | 498 - .../debug/__pycache__/__init__.cpython-37.pyc | Bin 12405 -> 0 bytes .../debug/__pycache__/console.cpython-37.pyc | Bin 7265 -> 0 bytes .../debug/__pycache__/repr.cpython-37.pyc | Bin 8563 -> 0 bytes .../debug/__pycache__/tbtools.cpython-37.pyc | Bin 18417 -> 0 bytes .../site-packages/werkzeug/debug/console.py | 218 - .../site-packages/werkzeug/debug/repr.py | 297 - .../werkzeug/debug/shared/FONT_LICENSE | 96 - .../werkzeug/debug/shared/console.png | Bin 507 -> 0 bytes .../werkzeug/debug/shared/debugger.js | 210 - .../werkzeug/debug/shared/jquery.js | 2 - .../werkzeug/debug/shared/less.png | Bin 191 -> 0 bytes .../werkzeug/debug/shared/more.png | Bin 200 -> 0 bytes .../werkzeug/debug/shared/source.png | Bin 818 -> 0 bytes .../werkzeug/debug/shared/style.css | 154 - .../werkzeug/debug/shared/ubuntu.ttf | Bin 70220 -> 0 bytes .../site-packages/werkzeug/debug/tbtools.py | 628 -- .../site-packages/werkzeug/exceptions.py | 829 -- .../site-packages/werkzeug/filesystem.py | 64 - .../site-packages/werkzeug/formparser.py | 584 -- .../python3.7/site-packages/werkzeug/http.py | 1307 --- .../python3.7/site-packages/werkzeug/local.py | 420 - .../werkzeug/middleware/__init__.py | 25 - .../__pycache__/__init__.cpython-37.pyc | Bin 708 -> 0 bytes .../__pycache__/dispatcher.cpython-37.pyc | Bin 2397 -> 0 bytes .../__pycache__/http_proxy.cpython-37.pyc | Bin 6312 -> 0 bytes .../__pycache__/lint.cpython-37.pyc | Bin 11620 -> 0 bytes .../__pycache__/profiler.cpython-37.pyc | Bin 4574 -> 0 bytes .../__pycache__/proxy_fix.cpython-37.pyc | Bin 5757 -> 0 bytes .../__pycache__/shared_data.cpython-37.pyc | Bin 8936 -> 0 bytes .../werkzeug/middleware/dispatcher.py | 66 - .../werkzeug/middleware/http_proxy.py | 219 - .../site-packages/werkzeug/middleware/lint.py | 408 - .../werkzeug/middleware/profiler.py | 132 - .../werkzeug/middleware/proxy_fix.py | 169 - .../werkzeug/middleware/shared_data.py | 293 - .../site-packages/werkzeug/posixemulation.py | 117 - .../site-packages/werkzeug/routing.py | 2210 ----- .../site-packages/werkzeug/security.py | 249 - .../site-packages/werkzeug/serving.py | 1117 --- .../python3.7/site-packages/werkzeug/test.py | 1123 --- .../site-packages/werkzeug/testapp.py | 241 - .../python3.7/site-packages/werkzeug/urls.py | 1138 --- .../site-packages/werkzeug/useragents.py | 202 - .../python3.7/site-packages/werkzeug/utils.py | 778 -- .../werkzeug/wrappers/__init__.py | 36 - .../__pycache__/__init__.cpython-37.pyc | Bin 1636 -> 0 bytes .../__pycache__/accept.cpython-37.pyc | Bin 2165 -> 0 bytes .../wrappers/__pycache__/auth.cpython-37.pyc | Bin 1652 -> 0 bytes .../__pycache__/base_request.cpython-37.pyc | Bin 21462 -> 0 bytes .../__pycache__/base_response.cpython-37.pyc | Bin 23136 -> 0 bytes .../common_descriptors.cpython-37.pyc | Bin 12725 -> 0 bytes .../wrappers/__pycache__/cors.cpython-37.pyc | Bin 3248 -> 0 bytes .../wrappers/__pycache__/etag.cpython-37.pyc | Bin 11518 -> 0 bytes .../wrappers/__pycache__/json.cpython-37.pyc | Bin 4267 -> 0 bytes .../__pycache__/request.cpython-37.pyc | Bin 1939 -> 0 bytes .../__pycache__/response.cpython-37.pyc | Bin 3468 -> 0 bytes .../__pycache__/user_agent.cpython-37.pyc | Bin 794 -> 0 bytes .../site-packages/werkzeug/wrappers/accept.py | 50 - .../site-packages/werkzeug/wrappers/auth.py | 33 - .../werkzeug/wrappers/base_request.py | 673 -- .../werkzeug/wrappers/base_response.py | 700 -- .../werkzeug/wrappers/common_descriptors.py | 341 - .../site-packages/werkzeug/wrappers/cors.py | 100 - .../site-packages/werkzeug/wrappers/etag.py | 304 - .../site-packages/werkzeug/wrappers/json.py | 145 - .../werkzeug/wrappers/request.py | 49 - .../werkzeug/wrappers/response.py | 84 - .../werkzeug/wrappers/user_agent.py | 14 - .../python3.7/site-packages/werkzeug/wsgi.py | 1000 -- .../wheel-0.34.2.dist-info/INSTALLER | 1 - .../wheel-0.34.2.dist-info/LICENSE.txt | 22 - .../wheel-0.34.2.dist-info/METADATA | 66 - .../wheel-0.34.2.dist-info/RECORD | 38 - .../wheel-0.34.2.dist-info/WHEEL | 6 - .../wheel-0.34.2.dist-info/entry_points.txt | 6 - .../wheel-0.34.2.dist-info/top_level.txt | 1 - .../python3.7/site-packages/wheel/__init__.py | 1 - .../python3.7/site-packages/wheel/__main__.py | 19 - .../wheel/__pycache__/__init__.cpython-37.pyc | Bin 158 -> 0 bytes .../wheel/__pycache__/__main__.cpython-37.pyc | Bin 551 -> 0 bytes .../wheel/__pycache__/_version.cpython-37.pyc | Bin 170 -> 0 bytes .../__pycache__/bdist_wheel.cpython-37.pyc | Bin 10804 -> 0 bytes .../__pycache__/macosx_libfile.cpython-37.pyc | Bin 6986 -> 0 bytes .../wheel/__pycache__/metadata.cpython-37.pyc | Bin 3698 -> 0 bytes .../__pycache__/pep425tags.cpython-37.pyc | Bin 7510 -> 0 bytes .../wheel/__pycache__/pkginfo.cpython-37.pyc | Bin 1529 -> 0 bytes .../wheel/__pycache__/util.cpython-37.pyc | Bin 1274 -> 0 bytes .../__pycache__/wheelfile.cpython-37.pyc | Bin 5470 -> 0 bytes .../python3.7/site-packages/wheel/_version.py | 4 - .../site-packages/wheel/bdist_wheel.py | 403 - .../site-packages/wheel/cli/__init__.py | 88 - .../cli/__pycache__/__init__.cpython-37.pyc | Bin 3000 -> 0 bytes .../cli/__pycache__/convert.cpython-37.pyc | Bin 6170 -> 0 bytes .../cli/__pycache__/install.cpython-37.pyc | Bin 139 -> 0 bytes .../wheel/cli/__pycache__/pack.cpython-37.pyc | Bin 2799 -> 0 bytes .../cli/__pycache__/unpack.cpython-37.pyc | Bin 903 -> 0 bytes .../site-packages/wheel/cli/convert.py | 269 - .../site-packages/wheel/cli/install.py | 0 .../python3.7/site-packages/wheel/cli/pack.py | 79 - .../site-packages/wheel/cli/unpack.py | 25 - .../site-packages/wheel/macosx_libfile.py | 341 - .../python3.7/site-packages/wheel/metadata.py | 138 - .../site-packages/wheel/pep425tags.py | 261 - .../python3.7/site-packages/wheel/pkginfo.py | 43 - .../lib/python3.7/site-packages/wheel/util.py | 46 - .../site-packages/wheel/wheelfile.py | 169 - .../backend/venv/lib/python3.7/site.py | 829 -- .../backend/venv/lib/python3.7/sre_compile.py | 784 -- .../venv/lib/python3.7/sre_constants.py | 261 - .../backend/venv/lib/python3.7/sre_parse.py | 1040 --- .../backend/venv/lib/python3.7/stat.py | 194 - .../backend/venv/lib/python3.7/struct.py | 15 - .../backend/venv/lib/python3.7/tarfile.py | 2537 ----- .../backend/venv/lib/python3.7/tempfile.py | 811 -- .../backend/venv/lib/python3.7/token.py | 160 - .../backend/venv/lib/python3.7/tokenize.py | 736 -- .../backend/venv/lib/python3.7/types.py | 295 - .../backend/venv/lib/python3.7/warnings.py | 561 -- .../backend/venv/lib/python3.7/weakref.py | 656 -- experiment/simulation/exp.html | 2 +- experiment/simulation/js/utils.js | 102 + .../simulation/weightedmatching_det.html | 2 +- .../simulation/weightedmatching_mean.html | 2 +- .../simulation/weightedmatching_sto.html | 2 +- 1378 files changed, 106 insertions(+), 235550 deletions(-) delete mode 100644 experiment/simulation/backend/Dockerfile delete mode 100644 experiment/simulation/backend/exp_weighted_matching/__init__.py delete mode 100755 experiment/simulation/backend/exp_weighted_matching/anneal_wmp_det.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/anneal_wmp_mean.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/anneal_wmp_sto.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/applytofig.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/drawgraph.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/exportfig.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/initMlp.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/init_wmp.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/initgraph.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/previewfig.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/restorefig.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/weightedmatchillustration.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/weightedmatching_det.m delete mode 100755 experiment/simulation/backend/exp_weighted_matching/weightedmatching_sto.m delete mode 100644 experiment/simulation/backend/requirements.txt delete mode 100644 experiment/simulation/backend/server.py delete mode 100644 experiment/simulation/backend/swagger.yaml delete mode 100644 experiment/simulation/backend/utils.py delete mode 100644 experiment/simulation/backend/venv/bin/activate delete mode 100644 experiment/simulation/backend/venv/bin/activate.csh delete mode 100644 experiment/simulation/backend/venv/bin/activate.fish delete mode 100644 experiment/simulation/backend/venv/bin/activate.ps1 delete mode 100644 experiment/simulation/backend/venv/bin/activate.xsh delete mode 100644 experiment/simulation/backend/venv/bin/activate_this.py delete mode 100755 experiment/simulation/backend/venv/bin/easy_install delete mode 100755 experiment/simulation/backend/venv/bin/easy_install-3.7 delete mode 100755 experiment/simulation/backend/venv/bin/flask delete mode 100755 experiment/simulation/backend/venv/bin/pip delete mode 100755 experiment/simulation/backend/venv/bin/pip3 delete mode 100755 experiment/simulation/backend/venv/bin/pip3.7 delete mode 120000 experiment/simulation/backend/venv/bin/python delete mode 100755 experiment/simulation/backend/venv/bin/python-config delete mode 120000 experiment/simulation/backend/venv/bin/python3 delete mode 100755 experiment/simulation/backend/venv/bin/python3.7 delete mode 100755 experiment/simulation/backend/venv/bin/wheel delete mode 120000 experiment/simulation/backend/venv/include/python3.7m delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/LICENSE.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__future__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/__future__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/_bootlocale.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/_collections_abc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/_weakrefset.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/abc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/base64.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/bisect.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/codecs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/copy.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/copyreg.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/enum.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/fnmatch.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/functools.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/genericpath.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/hashlib.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/heapq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/hmac.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/io.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/keyword.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/linecache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/locale.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/ntpath.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/operator.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/os.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/posixpath.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/random.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/re.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/reprlib.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/shutil.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/site.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_compile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_constants.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_parse.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/stat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/struct.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/tarfile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/tempfile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/token.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/tokenize.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/types.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/warnings.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/__pycache__/weakref.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/_bootlocale.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/_collections_abc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/_dummy_thread.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/_weakrefset.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/abc.py delete mode 100755 experiment/simulation/backend/venv/lib/python3.7/base64.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/bisect.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/codecs.py delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/collections delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/config-3.7m-x86_64-linux-gnu delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/copy.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/copyreg.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/distutils/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/distutils/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/distutils/distutils.cfg delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/encodings delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/enum.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/fnmatch.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/functools.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/genericpath.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/hashlib.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/heapq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/hmac.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/imp.py delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/importlib delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/io.py delete mode 100755 experiment/simulation/backend/venv/lib/python3.7/keyword.py delete mode 120000 experiment/simulation/backend/venv/lib/python3.7/lib-dynload delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/linecache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/locale.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/no-global-site-packages.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/ntpath.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/operator.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/orig-prefix.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/os.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/posixpath.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/random.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/re.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/reprlib.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/rlcompleter.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/shutil.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/LICENSE.rst delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/entry_points.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/LICENSE delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/LICENSE.rst delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/entry_points.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/LICENSE.rst delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/easy_install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/six.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/LICENSE.rst delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_bashcomplete.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_termui_impl.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_textwrap.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_unicodefun.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_winconsole.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/core.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/decorators.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/formatting.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/globals.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/termui.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/testing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/types.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_bashcomplete.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_termui_impl.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_textwrap.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_unicodefun.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_winconsole.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/core.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/decorators.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/formatting.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/globals.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/termui.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/testing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/types.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/click/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/easy_install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__main__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__main__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/app.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/blueprints.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/cli.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/config.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/ctx.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/debughelpers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/globals.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/helpers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/logging.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/sessions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/signals.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/templating.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/testing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/views.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/wrappers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/app.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/blueprints.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/cli.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/config.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/ctx.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/debughelpers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/globals.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/helpers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__pycache__/tag.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/tag.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/logging.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/sessions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/signals.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/templating.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/testing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/views.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/wrappers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__pycache__/core.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__pycache__/decorator.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__pycache__/extension.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/core.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/decorator.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/extension.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/flask_cors/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/LICENSE.rst delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/_json.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/encoding.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/exc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/jws.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/serializer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/signer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/timed.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/__pycache__/url_safe.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/_json.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/encoding.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/exc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/jws.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/serializer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/signer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/timed.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/itsdangerous/url_safe.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/_identifier.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/asyncfilters.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/asyncsupport.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/bccache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/compiler.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/constants.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/debug.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/defaults.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/environment.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/ext.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/filters.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/idtracking.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/lexer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/loaders.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/meta.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/nativetypes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/nodes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/optimizer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/runtime.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/sandbox.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/tests.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/__pycache__/visitor.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/_identifier.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/asyncfilters.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/asyncsupport.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/bccache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/compiler.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/constants.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/debug.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/defaults.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/environment.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/ext.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/filters.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/idtracking.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/lexer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/loaders.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/meta.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/nativetypes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/nodes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/optimizer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/runtime.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/sandbox.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/tests.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/jinja2/visitor.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/__pycache__/_constants.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/__pycache__/_native.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/_constants.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/_native.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/_speedups.c delete mode 100755 experiment/simulation/backend/venv/lib/python3.7/site-packages/markupsafe/_speedups.cpython-37m-x86_64-linux-gnu.so delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/LICENSE.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/entry_points.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip-20.0.2.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/__main__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/__pycache__/__main__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/build_env.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/cache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/configuration.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/legacy_resolve.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/locations.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/main.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/pep425tags.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/pyproject.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/build_env.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/main.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/command_context.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/main.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/req_command.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/check.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/completion.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/debug.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/download.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/hash.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/help.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/list.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/search.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/show.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/check.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/completion.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/configuration.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/debug.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/download.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/hash.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/help.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/list.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/search.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/show.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/commands/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/configuration.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__pycache__/base.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/base.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/installed.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/sdist.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/distributions/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/__pycache__/collector.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/collector.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/index/package_finder.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/legacy_resolve.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/locations.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/main.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/candidate.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/format_control.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/index.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/link.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/scheme.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/target_python.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/candidate.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/format_control.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/index.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/link.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/scheme.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/search_scope.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/selection_prefs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/target_python.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/models/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/auth.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/cache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/download.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/session.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/auth.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/cache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/download.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/session.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/network/xmlrpc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/__pycache__/check.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/check.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/editable_legacy.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/legacy.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/install/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/operations/prepare.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/pep425tags.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/pyproject.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/constructors.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/req_file.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/req_install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/req_set.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/constructors.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/req_file.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/req_install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/req_set.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/req_tracker.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/self_outdated_check.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/logging.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/marker_files.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/misc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/models.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/pkg_resources.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/typing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/ui.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/urls.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/distutils_args.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/encoding.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/entrypoints.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/filetypes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/glibc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/hashes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/inject_securetransport.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/marker_files.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/misc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/models.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/packaging.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/pkg_resources.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/subprocess.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/ui.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/unpacking.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/urls.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/virtualenv.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/utils/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/git.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/git.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/vcs/versioncontrol.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_internal/wheel_builder.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/appdirs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/contextlib2.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/distro.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/ipaddress.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/pyparsing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/retrying.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/__pycache__/six.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/appdirs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/cacert.pem delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/certifi/core.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langcyrillicmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5freq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5prober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/chardistribution.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/chardetect.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/codingstatemachine.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cp949prober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/enums.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escsm.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/eucjpprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrfreq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwfreq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312freq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312prober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/hebrewprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jisfreq.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jpcntx.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langgreekmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langthaimodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langturkishmodel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/latin1prober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcssm.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sjisprober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/universaldetector.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/utf8prober.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/chardet/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/contextlib2.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/misc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/shutil.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/database.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/index.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/util.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/distro.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_ihatexml.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_inputstream.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_tokenizer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/_base.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/py.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/constants.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/base.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/lint.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/serializer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/core.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/codec.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/core.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/ipaddress.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/_version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/_typing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_typing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/tags.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/packaging/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/_in_process.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/_in_process.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/build.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/check.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/colorlog.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/dirtools.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/envbuild.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/meta.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pep517/wrappers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/py31compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/__pycache__/bar.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/__pycache__/counter.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/bar.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/counter.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/progress/spinner.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pyparsing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/core.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/parser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/test.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__pycache__/writer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/core.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/parser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/test.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/writer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/api.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/help.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/models.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/api.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/auth.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/certs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/help.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/models.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/packages.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/structures.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/requests/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/retrying.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/six.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/labels.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/mklabels.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/tests.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/x_user_defined.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/__pycache__/py2_warn.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/__pycache__/py31compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__pycache__/six.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/appdirs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/markers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/requirements.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/pyparsing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/_vendor/six.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/extern/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/py2_warn.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/pkg_resources/py31compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/LICENSE delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/dependency_links.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/entry_points.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools-46.1.3.dist-info/zip-safe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/_imp.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/archive_util.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/build_meta.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/config.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/dep_util.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/depends.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/dist.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/errors.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/extension.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/glob.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/installer.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/launch.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/lib2to3_ex.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/monkey.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/msvc.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/namespaces.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/package_index.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/py27compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/py31compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/py33compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/py34compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/sandbox.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/site-patch.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/ssl_support.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/unicode_utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/__pycache__/windows_support.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_deprecation_warning.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_imp.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/__pycache__/six.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/ordered_set.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__about__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_structures.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/markers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/requirements.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/specifiers.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/tags.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/pyparsing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/_vendor/six.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/archive_util.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/build_meta.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/cli-32.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/cli-64.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/cli.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/alias.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/build_clib.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/build_ext.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/build_py.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/develop.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/dist_info.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/easy_install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/egg_info.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/install_lib.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/install_scripts.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/py36compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/register.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/rotate.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/saveopts.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/sdist.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/setopt.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/test.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/upload.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/__pycache__/upload_docs.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/alias.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/bdist_egg.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/bdist_wininst.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/build_clib.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/build_ext.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/build_py.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/develop.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/dist_info.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/easy_install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/egg_info.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/install_egg_info.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/install_lib.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/install_scripts.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/launcher manifest.xml delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/py36compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/register.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/rotate.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/saveopts.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/sdist.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/setopt.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/test.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/upload.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/command/upload_docs.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/config.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/dep_util.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/depends.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/dist.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/errors.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/extension.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/extern/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/extern/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/glob.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/gui-32.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/gui-64.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/gui.exe delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/installer.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/launch.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/lib2to3_ex.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/monkey.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/msvc.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/namespaces.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/package_index.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/py27compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/py31compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/py33compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/py34compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/sandbox.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/script (dev).tmpl delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/script.tmpl delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/site-patch.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/ssl_support.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/unicode_utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/setuptools/windows_support.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/LICENSE delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six-1.14.0.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/six.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/_compat.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/_internal.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/_reloader.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/datastructures.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/exceptions.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/filesystem.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/formparser.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/http.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/local.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/posixemulation.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/routing.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/security.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/serving.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/test.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/testapp.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/urls.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/useragents.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/utils.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/__pycache__/wsgi.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/_compat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/_internal.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/_reloader.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/datastructures.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/__pycache__/console.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/__pycache__/repr.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/console.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/repr.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/FONT_LICENSE delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/console.png delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/debugger.js delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/jquery.js delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/less.png delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/more.png delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/source.png delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/style.css delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/ubuntu.ttf delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/tbtools.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/exceptions.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/filesystem.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/formparser.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/http.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/local.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/lint.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/dispatcher.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/http_proxy.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/lint.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/profiler.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/proxy_fix.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/shared_data.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/posixemulation.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/routing.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/security.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/serving.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/test.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/testapp.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/urls.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/useragents.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/utils.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/accept.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/auth.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_request.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_response.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/common_descriptors.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/cors.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/etag.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/json.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/request.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/response.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/user_agent.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/accept.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/auth.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/base_request.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/common_descriptors.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/cors.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/etag.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/json.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/request.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/response.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/user_agent.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wsgi.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/INSTALLER delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/LICENSE.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/METADATA delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/RECORD delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/WHEEL delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/entry_points.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/top_level.txt delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__main__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__main__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/_version.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/bdist_wheel.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/macosx_libfile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/metadata.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pep425tags.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pkginfo.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/util.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/wheelfile.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/_version.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__init__.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/__init__.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/convert.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/install.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/pack.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/unpack.cpython-37.pyc delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/convert.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/install.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/pack.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/unpack.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/macosx_libfile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/metadata.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pep425tags.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pkginfo.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/util.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/wheelfile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/site.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/sre_compile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/sre_constants.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/sre_parse.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/stat.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/struct.py delete mode 100755 experiment/simulation/backend/venv/lib/python3.7/tarfile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/tempfile.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/token.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/tokenize.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/types.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/warnings.py delete mode 100644 experiment/simulation/backend/venv/lib/python3.7/weakref.py create mode 100644 experiment/simulation/js/utils.js diff --git a/experiment/simulation/backend/Dockerfile b/experiment/simulation/backend/Dockerfile deleted file mode 100644 index f8e9f8b..0000000 --- a/experiment/simulation/backend/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM ubuntu:18.04 - -RUN apt update && \ - apt install -y octave python3 python3-pip - -RUN octave --eval 'pkg install -forge nnet' - -COPY . / - -RUN pip3 install -r requirements.txt - -CMD python3 server.py diff --git a/experiment/simulation/backend/exp_weighted_matching/__init__.py b/experiment/simulation/backend/exp_weighted_matching/__init__.py deleted file mode 100644 index c570dae..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -from utils import * - -EXP_NAME = "weighted_matching" - - -def init_graph(nodeloc, token): - clear_files(10, token) - - res = run_octave(EXP_NAME, "init_wmp", nodeloc, token) - - if res: - return res - - images = read_all_pngs(EXP_NAME, token, 1) - - return jsonify(images=images, result="") - - -def start_annealing(method, nodeloc, token): - res = run_octave(EXP_NAME, f"anneal_wmp_{method}", nodeloc, token) - - if res: - return res - - images = read_all_pngs(EXP_NAME, token) - result = read_result(EXP_NAME, token) - - return jsonify(images=images, result=result) - - -num_map = { - "det": "det", - "mean": "mean", - "sto": "sto", -} - - -def runexp(data, part_num): - nodeloc = data.get("nodeloc") - token = data.get("token") - - if data.get("annealflag") == "1": - return start_annealing(num_map[part_num], nodeloc, token) - - if data.get("initflag") == "1": - return init_graph(nodeloc, token) - - return jsonify(success=True) diff --git a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_det.m b/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_det.m deleted file mode 100755 index b1bbdae..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_det.m +++ /dev/null @@ -1,95 +0,0 @@ -function finalstate = anneal_wmp_det(points, filename, initstate) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - - fid=fopen(strcat(filename, "-result.txt"),'w'); - - N=length(points); - M=nchoosek(N,2); - if(~exist('initstate')) - initstate=(rand(M,1)-0.5)>0; - end - initstate=initstate(:); - - fprintf(fid,'Initial state:\n'); - fprintf(fid,'%d ',initstate); - fprintf(fid,'\n'); - - d=zeros(N,N); - unit=[]; - th=[]; - k=1; - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - unit(k,:)=[i j]; - th=[th; d(i,j)]; - k=k+1; - end - end - d=d+d'; - - - % The nodes are (i,j): 12, 13, 14, 23, 24, 34 - - gamma=max(max(d))/(M/2); - W = zeros(M,M); - - for i=1:M - for j=i+1:M - if(any(~[unit(i,:)-unit(j,:) unit(i,[2 1])-unit(j,:)])) - W(i,j)=-gamma; - end - end - end - - W = W + W'; - - th=th-gamma; - - % Random initialization - %state = (rand(M,1)-0.5)>0; - %state=[0 1 1 0 0 0]' - state=initstate; - disp(state) - tempstate = zeros(M,1); - stateseq=[zeros(M,2) state]; - k=3; - while(norm(tempstate-state) ~= 0 & norm(stateseq(:,k)-stateseq(:,k-2))~=0 | k<10) - tempstate=state; - state=W*state+th; - %disp(state') - state=state>0; - %disp(state') - stateseq=[stateseq state]; - k=k+1; - %pause; - end - finalstate=state; - - disp(stateseq); - fprintf(fid,'\nOutput state of the nodes after each update:\n'); - for i=3:size(stateseq,2) - fprintf(fid,'%d ',stateseq(:,i)); - fprintf(fid,'\n'); - end - - - g=zeros(N,N); - ndx=unit(find(finalstate),:); - for i=1:size(ndx,1) - g([ndx(i,1)],[ndx(i,2)])=1; - end - %xyminmax = min_max(points'); - - drawgraph(g,points); - - print(strcat(filename, "-2.png")) - - fclose(fid); - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_mean.m b/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_mean.m deleted file mode 100755 index 54421e1..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_mean.m +++ /dev/null @@ -1,113 +0,0 @@ -function FinalState = anneal_wmp_mean(points, filename, InitState) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - - fid=fopen(strcat(filename, "-result.txt"),'w'); - - %points=[1 1;3 3;0 4;2 6]; - N=length(points); - M=nchoosek(N,2); - - if(~exist('InitState')) - InitState=rand(M,1); - end - - fprintf(fid,'Initial state:\n'); - fprintf(fid,'%d ',InitState); - fprintf(fid,'\n'); - fprintf(fid,'\n'); - fprintf(fid,'\nAvg. output state of the nodes after annealing for each temperature:\n'); - - d=zeros(N,N); - unit=[]; - th=[]; - k=1; - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - unit(k,:)=[i j]; - th=[th; d(i,j)]; - k=k+1; - end - end - d=d+d'; - - - % The nodes are (i,j): 12, 13, 14, 23, 24, 34 - - gamma=max(max(d))/(M/2); - W = zeros(M,M); - - for i=1:M - for j=i+1:M - if(any(~[unit(i,:)-unit(j,:) unit(i,[2 1])-unit(j,:)])) - W(i,j)=-gamma; - end - end - end - - W = W + W'; - - th=th-gamma; - th=th(:); - - % Random initialization - %State = (rand(M,1)-0.5)>0; - %state=[0 1 1 0 0 0]' - - State=InitState(:); - TempState=zeros(M,1); - disp(State') - - T=1; - dT=0.01; - i=1; - while(T>0) - %TempState=rand(M,1); - T=T-dT; - while(norm(State-TempState) >= 0.00001 & i<100) - TempState = State; - State = (W*State + th); - State = tanh(State/T); - i=i+1; - %disp(State') - %disp(norm(State-TempState)) - %pause; - end - disp(State') - - fprintf(fid,'%4.2f :',T); - fprintf(fid,'%d ',State>0); - fprintf(fid,'\n'); - - end - - [sval,spos]=sort(State,'descend'); - FinalState=zeros(M,1); - FinalState(spos(1:floor(N/2)))=1; - - disp(FinalState) - fprintf(fid,'\n'); - fprintf(fid,'\nFinal output state of the nodes:\n'); - fprintf(fid,'%d ',FinalState); - fprintf(fid,'\n'); - - - g=zeros(N,N); - ndx=unit(find(FinalState),:); - for i=1:size(ndx,1) - g([ndx(i,1)],[ndx(i,2)])=1; - end - %xyminmax = min_max(points'); - - drawgraph(g,points); - - print(strcat(filename, "-2.png")) - - fclose(fid); - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_sto.m b/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_sto.m deleted file mode 100755 index 8863fc5..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/anneal_wmp_sto.m +++ /dev/null @@ -1,124 +0,0 @@ -function FinalState = anneal_wmp_sto(points, filename, InitState) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - - fid=fopen(strcat(filename, "-result.txt"),'w'); - - %points=[1 1;3 3;0 4;2 6]; - N=length(points); - M=nchoosek(N,2); - - if(~exist('InitState')) - InitState=(rand(M,1)-0.5)>0; - end - - fprintf(fid,'Initial state:\n'); - fprintf(fid,'%d ',InitState); - fprintf(fid,'\n'); - fprintf(fid,'\n'); - fprintf(fid,'\nAvg. output state of the nodes after annealing for each temperature:\n'); - - d=zeros(N,N); - unit=[]; - th=[]; - k=1; - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - unit(k,:)=[i j]; - th=[th; d(i,j)]; - k=k+1; - end - end - d=d+d'; - - - % The nodes are (i,j): 12, 13, 14, 23, 24, 34 - - gamma=max(max(d))/(M/2); - W = zeros(M,M); - - for i=1:M - for j=i+1:M - if(any(~[unit(i,:)-unit(j,:) unit(i,[2 1])-unit(j,:)])) - W(i,j)=-gamma; - end - end - end - - W = W + W'; - - th=th-gamma; - th=th(:); - - % Random initialization - %State = (rand(M,1)-0.5)>0; - %state=[0 1 1 0 0 0]' - %State=InitState(:); - %disp(State') - - T=1; - dT=0.01; - - % PresentAvgState=rand(1,M); - PresentAvgState=InitState(:); - while(T>0.1) - TempAvgState=rand(M,1); - T=T-dT; - itn=1; - while(norm(PresentAvgState-TempAvgState) ~= 0 & itn<100) - itn=itn+1; - TempAvgState=PresentAvgState; - State = PresentAvgState; - for i=1:100 - %TempState=State; - State=W*State+th; - State=1./(1+exp(-State/T)); - PresentState(:,i)=State; - end - E=PresentState'*W*PresentState; - Energy=-0.5 * sum(E); - PartitionFn = sum(exp(-Energy/T)); - - Prob = exp(-Energy/T)/PartitionFn; - %size(PresentState) - %size(Prob) - PresentAvgState = sum([PresentState.*Prob(ones(size(PresentState,1),1),:)]')'; - %size(PresentAvgState) - %pause; - end - - fprintf(fid,'%4.2f :',T); - fprintf(fid,'%d ',PresentAvgState>0); - fprintf(fid,'\n'); - - end - - FinalState=PresentAvgState>0; - - disp(FinalState) - fprintf(fid,'\n'); - fprintf(fid,'\nFinal output state of the nodes:\n'); - fprintf(fid,'%d ',FinalState); - fprintf(fid,'\n'); - - - g=zeros(N,N); - ndx=unit(find(FinalState),:); - for i=1:size(ndx,1) - g([ndx(i,1)],[ndx(i,2)])=1; - end - %xyminmax = min_max(points'); - - drawgraph(g,points); - - print wmpoutput.png - print(strcat(filename, "-2.png")) - - fclose(fid); - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/applytofig.m b/experiment/simulation/backend/exp_weighted_matching/applytofig.m deleted file mode 100755 index bff831f..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/applytofig.m +++ /dev/null @@ -1,19 +0,0 @@ -function old = applytofig(h,varargin) - %APPLYTOFIG Apply EXPORTFIG options to figure. - % OLD = APPLYTOFIG(H) applies the default EXPORTFIG options to - % the figure with handle H and returns the state-difference - % structure in OLD. - % OLD = APPLYTOFIG(H, OPTIONS) applies OPTIONS to H as described - % in EXPORTFIG. - % OLD = APPLYTOFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) applies the - % specified parameter-value pairs to H as described in EXPORTFIG. - % - % Use RESTOREFIG(H,OLD) to restore the figure to its state before - % applyfig was called. - % - % See also EXPORTFIG, PREVIEWFIG, RESTOREFIG. - - % Copyright 2000-2009 The MathWorks, Inc - - temp = tempname; - old = exportfig(h,temp, varargin{:},'applystyle',1); diff --git a/experiment/simulation/backend/exp_weighted_matching/drawgraph.m b/experiment/simulation/backend/exp_weighted_matching/drawgraph.m deleted file mode 100755 index 0cd8e09..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/drawgraph.m +++ /dev/null @@ -1,25 +0,0 @@ -function drawgraph(g,nodes) - N=length(nodes); - figure; - gplot(g,nodes);hold on; - plot(nodes(:,1),nodes(:,2),'o','markersize',30); - - - %xlim([xyminmax(1,1)-1,xyminmax(1,2)+1]); - %ylim([xyminmax(2,1)-1,xyminmax(2,2)+1]); - xymin=min(min(nodes))-1; - xymax=max(max(nodes))+1; - xlim([xymin xymax]); - ylim([xymin xymax]); - - for i=1:N;text(nodes(i,1),nodes(i,2)+.7,num2str(i),'fontsize',20);end - %for i=1:N;text(nodes(i,1)-.1,nodes(i,2),num2str(i));end - - - lh=findall(gcf,'type','line'); - set(lh,'linewidth',6); - % ah=findall(gcf,'type','axes'); - % th=findall(gcf,'type','text'); - % set([ah;th],'fontsize',16,'fontweight','bold'); - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/exportfig.m b/experiment/simulation/backend/exp_weighted_matching/exportfig.m deleted file mode 100755 index f3ad455..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/exportfig.m +++ /dev/null @@ -1,1057 +0,0 @@ -function varargout = exportfig(varargin) - %EXPORTFIG Export a figure. - % EXPORTFIG(H, FILENAME) writes the figure H to FILENAME. H is - % a figure handle and FILENAME is a string that specifies the - % name of the output file. - % - % EXPORTFIG(H, FILENAME, OPTIONS) writes the figure H to FILENAME - % with options initially specified by the structure OPTIONS. The - % field names of OPTIONS must be legal parameters listed below - % and the field values must be legal values for the corresponding - % parameter. Default options can be set in releases prior to R12 - % by storing the OPTIONS structure in the root object's appdata - % with the command - % setappdata(0,'exportfigdefaults', OPTIONS) - % and for releases after R12 by setting the preference with the - % command - % setpref('exportfig', 'defaults', OPTIONS) - % - % EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies - % parameters that control various characteristics of the output - % file. Any parameter value can be the string 'auto' which means - % the parameter uses the default factory behavior, overriding - % any other default for the parameter. - % - % Format Paramter: - % 'Format' a string - % specifies the output format. Defaults to 'eps'. For a - % list of export formats type 'help print'. - % 'Preview' one of the strings 'none', 'tiff' - % specifies a preview for EPS files. Defaults to 'none'. - % - % Size Parameters: - % 'Width' a positive scalar - % specifies the width in the figure's PaperUnits - % 'Height' a positive scalar - % specifies the height in the figure's PaperUnits - % 'Bounds' one of the strings 'tight', 'loose' - % specifies a tight or loose bounding box. Defaults to 'tight'. - % 'BoundsCode' one of the strings 'internal', 'mcode' - % specifies whether to use the internal EPS code or - % general m-code for computing bounding boxes. Defaults to - % 'internal'. - % 'Reference' an axes handle or a string - % specifies that the width and height parameters - % are relative to the given axes. If a string is - % specified then it must evaluate to an axes handle. - % - % Specifying only one dimension sets the other dimension - % so that the exported aspect ratio is the same as the - % figure's or reference axes' current aspect ratio. - % If neither dimension is specified the size defaults to - % the width and height from the figure's or reference - % axes' size. Tight bounding boxes are only computed for - % 2-D views and in that case the computed bounds enclose all - % text objects. - % - % Rendering Parameters: - % 'Color' one of the strings 'bw', 'gray', 'cmyk' - % 'bw' specifies that lines and text are exported in - % black and all other objects in grayscale - % 'gray' specifies that all objects are exported in grayscale - % 'rgb' specifies that all objects are exported in color - % using the RGB color space - % 'cmyk' specifies that all objects are exported in color - % using the CMYK color space - % 'Renderer' one of 'painters', 'zbuffer', 'opengl' - % specifies the renderer to use - % 'Resolution' a positive scalar - % specifies the resolution in dots-per-inch. - % 'LockAxes' one of 0 or 1 - % specifies that all axes limits and ticks should be fixed - % while exporting. - % - % The default color setting is 'bw'. - % - % Font Parameters: - % 'FontMode' one of the strings 'scaled', 'fixed' - % 'FontSize' a positive scalar - % in 'scaled' mode multiplies with the font size of each - % text object to obtain the exported font size - % in 'fixed' mode specifies the font size of all text - % objects in points - % 'DefaultFixedFontSize' a positive scalar - % in 'fixed' mode specified the default font size in - % points - % 'FontSizeMin' a positive scalar - % specifies the minimum font size allowed after scaling - % 'FontSizeMax' a positive scalar - % specifies the maximum font size allowed after scaling - % 'FontEncoding' one of the strings 'latin1', 'adobe' - % specifies the character encoding of the font - % 'SeparateText' one of 0 or 1 - % specifies that the text objects are stored in separate - % file as EPS with the base filename having '_t' appended. - % - % If FontMode is 'scaled' but FontSize is not specified then a - % scaling factor is computed from the ratio of the size of the - % exported figure to the size of the actual figure. - % - % The default 'FontMode' setting is 'scaled'. - % - % Line Width Parameters: - % 'LineMode' one of the strings 'scaled', 'fixed' - % 'LineWidth' a positive scalar - % 'DefaultFixedLineWidth' a positive scalar - % 'LineWidthMin' a positive scalar - % specifies the minimum line width allowed after scaling - % 'LineWidthMax' a positive scalar - % specifies the maximum line width allowed after scaling - % The semantics of 'Line' parameters are exactly the - % same as the corresponding 'Font' parameters, except that - % they apply to line widths instead of font sizes. - % - % Style Map Parameter: - % 'LineStyleMap' one of [], 'bw', or a function name or handle - % specifies how to map line colors to styles. An empty - % style map means styles are not changed. The style map - % 'bw' is a built-in mapping that maps lines with the same - % color to the same style and otherwise cycles through the - % available styles. A user-specified map is a function - % that takes as input a cell array of line objects and - % outputs a cell array of line style strings. The default - % map is []. - % - % Examples: - % exportfig(gcf,'fig1.eps','height',3); - % Exports the current figure to the file named 'fig1.eps' with - % a height of 3 inches (assuming the figure's PaperUnits is - % inches) and an aspect ratio the same as the figure's aspect - % ratio on screen. - % - % opts = struct('FontMode','fixed','FontSize',10,'height',3); - % exportfig(gcf, 'fig2.eps', opts, 'height', 5); - % Exports the current figure to 'fig2.eps' with all - % text in 10 point fonts and with height 5 inches. - % - % See also PREVIEWFIG, APPLYTOFIG, RESTOREFIG, PRINT. - - % Copyright 2000-2009 The MathWorks, Inc. - - if (nargin < 2) - error('Too few input arguments'); - end - - % exportfig(H, filename, [options,] ...) - H = varargin{1}; - if ~LocalIsHG(H,'figure') - error('First argument must be a handle to a figure.'); - end - filename = varargin{2}; - if ~ischar(filename) - error('Second argument must be a string.'); - end - paramPairs = {varargin{3:end}}; -if nargin > 2 - if isstruct(paramPairs{1}) - pcell = LocalToCell(paramPairs{1}); - paramPairs = {pcell{:}, paramPairs{2:end}}; -end -end -verstr = version; -majorver = str2num(verstr(1)); -defaults = []; -if majorver > 5 - if ispref('exportfig','defaults') - defaults = getpref('exportfig','defaults'); - end -elseif exist('getappdata') - defaults = getappdata(0,'exportfigdefaults'); -end -if ~isempty(defaults) - dcell = LocalToCell(defaults); - paramPairs = {dcell{:}, paramPairs{:}}; -end - -% Do some validity checking on param-value pairs -if (rem(length(paramPairs),2) ~= 0) - error(['Invalid input syntax. Optional parameters and values' ... - ' must be in pairs.']); -end - -auto.format = 'eps'; -auto.preview = 'none'; -auto.width = -1; -auto.height = -1; -auto.color = 'bw'; -auto.defaultfontsize=10; -auto.fontsize = -1; -auto.fontmode='scaled'; -auto.fontmin = 8; -auto.fontmax = 60; -auto.defaultlinewidth = 1.0; -auto.linewidth = -1; -auto.linemode=[]; -auto.linemin = 0.5; -auto.linemax = 100; -auto.fontencoding = 'latin1'; -auto.renderer = []; -auto.resolution = []; -auto.stylemap = []; -auto.applystyle = 0; -auto.refobj = -1; -auto.bounds = 'tight'; -auto.boundscode = 'internal'; -explicitbounds = 0; -auto.lockaxes = 1; -auto.separatetext = 0; -opts = auto; - -% Process param-value pairs -args = {}; -for k = 1:2:length(paramPairs) - param = lower(paramPairs{k}); - if ~ischar(param) - error('Optional parameter names must be strings'); - end - value = paramPairs{k+1}; - - switch (param) - case 'format' - opts.format = LocalCheckAuto(lower(value),auto.format); - if strcmp(opts.format,'preview') - error(['Format ''preview'' no longer supported. Use PREVIEWFIG' ... - ' instead.']); - end - case 'preview' - opts.preview = LocalCheckAuto(lower(value),auto.preview); - if ~strcmp(opts.preview,{'none','tiff'}) - error('Preview must be ''none'' or ''tiff''.'); - end - case 'width' - opts.width = LocalToNum(value, auto.width); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.width) - error('Width must be a numeric scalar > 0'); - end - end - case 'height' - opts.height = LocalToNum(value, auto.height); - if ~ischar(value) | ~strcmp(value,'auto') - if(~LocalIsPositiveScalar(opts.height)) - error('Height must be a numeric scalar > 0'); - end - end - case 'color' - opts.color = LocalCheckAuto(lower(value),auto.color); - if ~strcmp(opts.color,{'bw','gray','rgb','cmyk'}) - error('Color must be ''bw'', ''gray'',''rgb'' or ''cmyk''.'); - end - case 'fontmode' - opts.fontmode = LocalCheckAuto(lower(value),auto.fontmode); - if ~strcmp(opts.fontmode,{'scaled','fixed'}) - error('FontMode must be ''scaled'' or ''fixed''.'); - end - case 'fontsize' - opts.fontsize = LocalToNum(value,auto.fontsize); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.fontsize) - error('FontSize must be a numeric scalar > 0'); - end - end - case 'defaultfixedfontsize' - opts.defaultfontsize = LocalToNum(value,auto.defaultfontsize); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.defaultfontsize) - error('DefaultFixedFontSize must be a numeric scalar > 0'); - end - end - case 'fontsizemin' - opts.fontmin = LocalToNum(value,auto.fontmin); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.fontmin) - error('FontSizeMin must be a numeric scalar > 0'); - end - end - case 'fontsizemax' - opts.fontmax = LocalToNum(value,auto.fontmax); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.fontmax) - error('FontSizeMax must be a numeric scalar > 0'); - end - end - case 'fontencoding' - opts.fontencoding = LocalCheckAuto(lower(value),auto.fontencoding); - if ~strcmp(opts.fontencoding,{'latin1','adobe'}) - error('FontEncoding must be ''latin1'' or ''adobe''.'); - end - case 'linemode' - opts.linemode = LocalCheckAuto(lower(value),auto.linemode); - if ~strcmp(opts.linemode,{'scaled','fixed'}) - error('LineMode must be ''scaled'' or ''fixed''.'); - end - case 'linewidth' - opts.linewidth = LocalToNum(value,auto.linewidth); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.linewidth) - error('LineWidth must be a numeric scalar > 0'); - end - end - case 'defaultfixedlinewidth' - opts.defaultlinewidth = LocalToNum(value,auto.defaultlinewidth); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.defaultlinewidth) - error(['DefaultFixedLineWidth must be a numeric scalar >' ... - ' 0']); - end - end - case 'linewidthmin' - opts.linemin = LocalToNum(value,auto.linemin); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.linemin) - error('LineWidthMin must be a numeric scalar > 0'); - end - end - case 'linewidthmax' - opts.linemax = LocalToNum(value,auto.linemax); - if ~ischar(value) | ~strcmp(value,'auto') - if ~LocalIsPositiveScalar(opts.linemax) - error('LineWidthMax must be a numeric scalar > 0'); - end - end - case 'linestylemap' - opts.stylemap = LocalCheckAuto(value,auto.stylemap); - case 'renderer' - opts.renderer = LocalCheckAuto(lower(value),auto.renderer); - if ~ischar(value) | ~strcmp(value,'auto') - if ~strcmp(opts.renderer,{'painters','zbuffer','opengl'}) - error(['Renderer must be ''painters'', ''zbuffer'' or' ... - ' ''opengl''.']); - end - end - case 'resolution' - opts.resolution = LocalToNum(value,auto.resolution); - if ~ischar(value) | ~strcmp(value,'auto') - if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0)); - error('Resolution must be a numeric scalar >= 0'); - end - end - case 'applystyle' % means to apply the options and not export - opts.applystyle = 1; - case 'reference' - if ischar(value) - if strcmp(value,'auto') - opts.refobj = auto.refobj; - else - opts.refobj = eval(value); - end - else - opts.refobj = value; - end - if ~LocalIsHG(opts.refobj,'axes') - error('Reference object must evaluate to an axes handle.'); - end - case 'bounds' - opts.bounds = LocalCheckAuto(lower(value),auto.bounds); - explicitbounds = 1; - if ~strcmp(opts.bounds,{'tight','loose'}) - error('Bounds must be ''tight'' or ''loose''.'); - end - case 'boundscode' - opts.boundscode = LocalCheckAuto(lower(value),auto.boundscode); - if ~strcmp(opts.boundscode,{'internal','mcode'}) - error('BoundsCode must be ''internal'' or ''mcode''.'); - end - case 'lockaxes' - opts.lockaxes = LocalToNum(value,auto.lockaxes); - case 'separatetext' - opts.separatetext = LocalToNum(value,auto.separatetext); - otherwise - error(['Unrecognized option ' param '.']); - end -end - -% make sure figure is up-to-date -drawnow; - -allLines = findall(H, 'type', 'line'); -allText = findall(H, 'type', 'text'); -allAxes = findall(H, 'type', 'axes'); -allImages = findall(H, 'type', 'image'); -allLights = findall(H, 'type', 'light'); -allPatch = findall(H, 'type', 'patch'); -allSurf = findall(H, 'type', 'surface'); -allRect = findall(H, 'type', 'rectangle'); -allFont = [allText; allAxes]; -allColor = [allLines; allText; allAxes; allLights]; -allMarker = [allLines; allPatch; allSurf]; -allEdge = [allPatch; allSurf]; -allCData = [allImages; allSurf]; - -% need to explicitly get ticks for some invisible figures -get(allAxes,'yticklabel'); - -old.objs = {}; -old.prop = {}; -old.values = {}; - -% Process format -if strncmp(opts.format,'eps',3) & ~strcmp(opts.preview,'none') - args = {args{:}, ['-' opts.preview]}; -end - -hadError = 0; -oldwarn = warning; -try - - % lock axes limits, ticks and labels if requested - if opts.lockaxes - old = LocalManualAxesMode(old, allAxes, 'TickMode'); - old = LocalManualAxesMode(old, allAxes, 'TickLabelMode'); - old = LocalManualAxesMode(old, allAxes, 'LimMode'); - end - - % Process size parameters - figurePaperUnits = get(H, 'PaperUnits'); - oldFigureUnits = get(H, 'Units'); - oldFigPos = get(H,'Position'); - set(H, 'Units', figurePaperUnits); - figPos = get(H,'Position'); - refsize = figPos(3:4); - if opts.refobj ~= -1 - oldUnits = get(opts.refobj, 'Units'); - set(opts.refobj, 'Units', figurePaperUnits); - r = get(opts.refobj, 'Position'); - refsize = r(3:4); - set(opts.refobj, 'Units', oldUnits); - end - aspectRatio = refsize(1)/refsize(2); - if (opts.width == -1) & (opts.height == -1) - opts.width = refsize(1); - opts.height = refsize(2); - elseif (opts.width == -1) - opts.width = opts.height * aspectRatio; - elseif (opts.height == -1) - opts.height = opts.width / aspectRatio; - end - wscale = opts.width/refsize(1); - hscale = opts.height/refsize(2); - sizescale = min(wscale,hscale); - old = LocalPushOldData(old,H,'PaperPositionMode', ... - get(H,'PaperPositionMode')); - set(H, 'PaperPositionMode', 'auto'); - newPos = [figPos(1) figPos(2)+figPos(4)*(1-hscale) ... - wscale*figPos(3) hscale*figPos(4)]; -set(H, 'Position', newPos); -set(H, 'Units', oldFigureUnits); - -old = LocalPushOldData(old,H,'Color', ... - get(H,'Color')); -set(H,'Color','w'); - -% process line-style map -if ~isempty(opts.stylemap) & ~isempty(allLines) - oldlstyle = LocalGetAsCell(allLines,'LineStyle'); - old = LocalPushOldData(old, allLines, {'LineStyle'}, ... - oldlstyle); - newlstyle = oldlstyle; - if ischar(opts.stylemap) & strcmpi(opts.stylemap,'bw') - newlstyle = LocalMapColorToStyle(allLines); - else - try - newlstyle = feval(opts.stylemap,allLines); - catch - warning(['Skipping stylemap. ' lasterr]); - end - end - set(allLines,{'LineStyle'},newlstyle); -end - -% Process rendering parameters -switch (opts.color) - case {'bw', 'gray'} - if ~strcmp(opts.color,'bw') & strncmp(opts.format,'eps',3) - opts.format = [opts.format 'c']; - end - args = {args{:}, ['-d' opts.format]}; - - %compute and set gray colormap - oldcmap = get(H,'Colormap'); - newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3); - newcmap = [newgrays newgrays newgrays]; - old = LocalPushOldData(old, H, 'Colormap', oldcmap); - set(H, 'Colormap', newcmap); - - %compute and set ColorSpec and CData properties - old = LocalUpdateColors(allColor, 'color', old); - old = LocalUpdateColors(allAxes, 'xcolor', old); - old = LocalUpdateColors(allAxes, 'ycolor', old); - old = LocalUpdateColors(allAxes, 'zcolor', old); - old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old); - old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old); - old = LocalUpdateColors(allEdge, 'EdgeColor', old); - old = LocalUpdateColors(allEdge, 'FaceColor', old); - old = LocalUpdateColors(allCData, 'CData', old); - - if strcmp(opts.color,'bw') - lcolor = LocalGetAsCell(allLines,'color'); - n = length(lcolor); - for k=1:n - if (lcolor{k}(1) < 1-eps) - set(allLines(k),'color','k'); - end - end - end - case {'rgb','cmyk'} - if strncmp(opts.format,'eps',3) - opts.format = [opts.format 'c']; - args = {args{:}, ['-d' opts.format]}; - if strcmp(opts.color,'cmyk') - args = {args{:}, '-cmyk'}; - end - else - args = {args{:}, ['-d' opts.format]}; - end - otherwise - error('Invalid Color parameter'); -end -if (~isempty(opts.renderer)) - args = {args{:}, ['-' opts.renderer]}; -end -if (~isempty(opts.resolution)) | ~strncmp(opts.format,'eps',3) - if isempty(opts.resolution) - opts.resolution = 0; - end - args = {args{:}, ['-r' int2str(opts.resolution)]}; -end - -% Process font parameters -if ~isempty(opts.fontmode) - oldfonts = LocalGetAsCell(allFont,'FontSize'); - oldfontunits = LocalGetAsCell(allFont,'FontUnits'); - set(allFont,'FontUnits','points'); - switch (opts.fontmode) - case 'fixed' - if (opts.fontsize == -1) - set(allFont,'FontSize',opts.defaultfontsize); - else - set(allFont,'FontSize',opts.fontsize); - end - case 'scaled' - if (opts.fontsize == -1) - scale = sizescale; - else - scale = opts.fontsize; - end - newfonts = LocalScale(oldfonts,scale,opts.fontmin,opts.fontmax); - set(allFont,{'FontSize'},newfonts); - otherwise - error('Invalid FontMode parameter'); - end - old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts); - old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits); -end -if strcmp(opts.fontencoding,'adobe') & strncmp(opts.format,'eps',3) - args = {args{:}, '-adobecset'}; -end - -% Process line parameters -if ~isempty(opts.linemode) - oldlines = LocalGetAsCell(allMarker,'LineWidth'); - old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines); - switch (opts.linemode) - case 'fixed' - if (opts.linewidth == -1) - set(allMarker,'LineWidth',opts.defaultlinewidth); - else - set(allMarker,'LineWidth',opts.linewidth); - end - case 'scaled' - if (opts.linewidth == -1) - scale = sizescale; - else - scale = opts.linewidth; - end - newlines = LocalScale(oldlines, scale, opts.linemin, opts.linemax); - set(allMarker,{'LineWidth'},newlines); - end -end - -% adjust figure bounds to surround axes -if strcmp(opts.bounds,'tight') - if (~strncmp(opts.format,'eps',3) & LocalHas3DPlot(allAxes)) | ... - (strncmp(opts.format,'eps',3) & opts.separatetext) - if (explicitbounds == 1) - warning(['Cannot compute ''tight'' bounds. Using ''loose''' ... - ' bounds.']); - end - opts.bounds = 'loose'; - end -end -warning('off'); -if ~isempty(allAxes) - usemcode = 1; - if strncmp(opts.format,'eps',3) - if strcmp(opts.boundscode,'internal') - if strcmp(opts.bounds,'loose') - args = {args{:}, '-loose'}; - end - old = LocalPushOldData(old,H,'Position', oldFigPos); - usemcode = 0; - else - usemcode = 1; - end - end - if strcmp(opts.bounds,'tight') & usemcode - oldaunits = LocalGetAsCell(allAxes,'Units'); - oldapos = LocalGetAsCell(allAxes,'Position'); - oldtunits = LocalGetAsCell(allText,'units'); - oldtpos = LocalGetAsCell(allText,'Position'); - set(allAxes,'units','points'); - apos = LocalGetAsCell(allAxes,'Position'); - oldunits = get(H,'Units'); - set(H,'units','points'); - origfr = get(H,'position'); - fr = []; - for k=1:length(allAxes) - if ~strcmpi(get(allAxes(k),'Tag'),'legend') - axesR = apos{k}; - r = LocalAxesTightBoundingBox(axesR, allAxes(k)); - if ~isempty(r) - r(1:2) = r(1:2) + axesR(1:2); - fr = LocalUnionRect(fr,r); - end - end - end - if isempty(fr) - fr = [0 0 origfr(3:4)]; - end - for k=1:length(allAxes) - ax = allAxes(k); - r = apos{k}; - r(1:2) = r(1:2) - fr(1:2); - set(ax,'Position',r); - end - old = LocalPushOldData(old, allAxes, {'Position'}, oldapos); - old = LocalPushOldData(old, allText, {'Position'}, oldtpos); - old = LocalPushOldData(old, allText, {'Units'}, oldtunits); - old = LocalPushOldData(old, allAxes, {'Units'}, oldaunits); - old = LocalPushOldData(old, H, 'Position', oldFigPos); - old = LocalPushOldData(old, H, 'Units', oldFigureUnits); - r = [origfr(1) origfr(2)+origfr(4)-fr(4) fr(3:4)]; - set(H,'Position',r); - end -end - -% Process text in a separate file if needed -if opts.separatetext & ~opts.applystyle - % First hide all text and export - oldtvis = LocalGetAsCell(allText,'visible'); - set(allText,'visible','off'); - oldax = LocalGetAsCell(allAxes,'XTickLabel',1); - olday = LocalGetAsCell(allAxes,'YTickLabel',1); - oldaz = LocalGetAsCell(allAxes,'ZTickLabel',1); - null = cell(length(oldax),1); - [null{:}] = deal([]); - set(allAxes,{'XTickLabel'},null); - set(allAxes,{'YTickLabel'},null); - set(allAxes,{'ZTickLabel'},null); - print(H, filename, args{:}); - set(allText,{'Visible'},oldtvis); - set(allAxes,{'XTickLabel'},oldax); - set(allAxes,{'YTickLabel'},olday); - set(allAxes,{'ZTickLabel'},oldaz); - % Now hide all non-text and export as eps in painters - [path, name, ext] = fileparts(filename); - tfile = fullfile(path,[name '_t.eps']); - tfile2 = fullfile(path,[name '_t2.eps']); - foundRenderer = 0; - for k=1:length(args) - if strncmp('-d',args{k},2) - args{k} = '-deps'; - elseif strncmp('-zbuffer',args{k},8) | ... - strncmp('-opengl', args{k},6) - args{k} = '-painters'; - foundRenderer = 1; - end - end - if ~foundRenderer - args = {args{:}, '-painters'}; - end - allNonText = [allLines; allLights; allPatch; ... - allImages; allSurf; allRect]; -oldvis = LocalGetAsCell(allNonText,'visible'); -oldc = LocalGetAsCell(allAxes,'color'); -oldaxg = LocalGetAsCell(allAxes,'XGrid'); -oldayg = LocalGetAsCell(allAxes,'YGrid'); -oldazg = LocalGetAsCell(allAxes,'ZGrid'); -[null{:}] = deal('off'); -set(allAxes,{'XGrid'},null); -set(allAxes,{'YGrid'},null); -set(allAxes,{'ZGrid'},null); -set(allNonText,'Visible','off'); -set(allAxes,'Color','none'); -print(H, tfile2, args{:}); -set(allNonText,{'Visible'},oldvis); -set(allAxes,{'Color'},oldc); -set(allAxes,{'XGrid'},oldaxg); -set(allAxes,{'YGrid'},oldayg); -set(allAxes,{'ZGrid'},oldazg); -%hack up the postscript file -fid1 = fopen(tfile,'w'); -fid2 = fopen(tfile2,'r'); -line = fgetl(fid2); -while ischar(line) - if strncmp(line,'%%Title',7) - fprintf(fid1,'%s\n',['%%Title: ', tfile]); - elseif (length(line) < 3) - fprintf(fid1,'%s\n',line); - elseif ~strcmp(line(end-2:end),' PR') & ... - ~strcmp(line(end-1:end),' L') - fprintf(fid1,'%s\n',line); - end - line = fgetl(fid2); -end -fclose(fid1); -fclose(fid2); -delete(tfile2); - -elseif ~opts.applystyle - drawnow; - print(H, filename, args{:}); -end -warning(oldwarn); - -catch - warning(oldwarn); - hadError = 1; -end - -% Restore figure settings -if opts.applystyle - varargout{1} = old; -else - for n=1:length(old.objs) - if ~iscell(old.values{n}) & iscell(old.prop{n}) - old.values{n} = {old.values{n}}; - end - set(old.objs{n}, old.prop{n}, old.values{n}); - end -end - -if hadError - error(deblank(lasterr)); -end - -% -% Local Functions -% - -function outData = LocalPushOldData(inData, objs, prop, values) - outData.objs = {objs, inData.objs{:}}; - outData.prop = {prop, inData.prop{:}}; - outData.values = {values, inData.values{:}}; - - function cellArray = LocalGetAsCell(fig,prop,allowemptycell); - cellArray = get(fig,prop); - if nargin < 3 - allowemptycell = 0; - end - if ~iscell(cellArray) & (allowemptycell | ~isempty(cellArray)) - cellArray = {cellArray}; - end - - function newArray = LocalScale(inArray, scale, minv, maxv) - n = length(inArray); - newArray = cell(n,1); - for k=1:n - newArray{k} = min(maxv,max(minv,scale*inArray{k}(1))); - end - - function gray = LocalMapToGray1(color) - gray = color; - if ischar(color) - switch color(1) - case 'y' - color = [1 1 0]; - case 'm' - color = [1 0 1]; - case 'c' - color = [0 1 1]; - case 'r' - color = [1 0 0]; - case 'g' - color = [0 1 0]; - case 'b' - color = [0 0 1]; - case 'w' - color = [1 1 1]; - case 'k' - color = [0 0 0]; - end - end - if ~ischar(color) - gray = 0.30*color(1) + 0.59*color(2) + 0.11*color(3); - end - - function newArray = LocalMapToGray(inArray); - n = length(inArray); - newArray = cell(n,1); - for k=1:n - color = inArray{k}; - if ~isempty(color) - color = LocalMapToGray1(color); - end - if isempty(color) | ischar(color) - newArray{k} = color; - else - newArray{k} = [color color color]; - end - end - - function newArray = LocalMapColorToStyle(inArray); - inArray = LocalGetAsCell(inArray,'Color'); - n = length(inArray); - newArray = cell(n,1); - styles = {'-','--',':','-.'}; - uniques = []; - nstyles = length(styles); - for k=1:n - gray = LocalMapToGray1(inArray{k}); - if isempty(gray) | ischar(gray) | gray < .05 - newArray{k} = '-'; - else - if ~isempty(uniques) & any(gray == uniques) - ind = find(gray==uniques); - else - uniques = [uniques gray]; - ind = length(uniques); - end - newArray{k} = styles{mod(ind-1,nstyles)+1}; - end - end - - function newArray = LocalMapCData(inArray); - n = length(inArray); - newArray = cell(n,1); - for k=1:n - color = inArray{k}; - if (ndims(color) == 3) & isa(color,'double') - gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3); - color(:,:,1) = gray; - color(:,:,2) = gray; - color(:,:,3) = gray; - end - newArray{k} = color; - end - - function outData = LocalUpdateColors(inArray, prop, inData) - value = LocalGetAsCell(inArray,prop); - outData.objs = {inData.objs{:}, inArray}; - outData.prop = {inData.prop{:}, {prop}}; - outData.values = {inData.values{:}, value}; - if (~isempty(value)) - if strcmp(prop,'CData') - value = LocalMapCData(value); - else - value = LocalMapToGray(value); - end - set(inArray,{prop},value); - end - - function bool = LocalIsPositiveScalar(value) - bool = isnumeric(value) & ... - prod(size(value)) == 1 & ... - value > 0; - - function value = LocalToNum(value,auto) - if ischar(value) - if strcmp(value,'auto') - value = auto; - else - value = str2num(value); - end - end - - %convert a struct to {field1,val1,field2,val2,...} - function c = LocalToCell(s) - f = fieldnames(s); - v = struct2cell(s); - opts = cell(2,length(f)); - opts(1,:) = f; - opts(2,:) = v; - c = {opts{:}}; - - function c = LocalIsHG(obj,hgtype) - c = 0; - if (length(obj) == 1) & ishandle(obj) - c = strcmp(get(obj,'type'),hgtype); - end - - function c = LocalHas3DPlot(a) - zticks = LocalGetAsCell(a,'ZTickLabel'); - c = 0; - for k=1:length(zticks) - if ~isempty(zticks{k}) - c = 1; - return; - end - end - - function r = LocalUnionRect(r1,r2) - if isempty(r1) - r = r2; - elseif isempty(r2) - r = r1; - elseif max(r2(3:4)) > 0 - left = min(r1(1),r2(1)); - bot = min(r1(2),r2(2)); - right = max(r1(1)+r1(3),r2(1)+r2(3)); - top = max(r1(2)+r1(4),r2(2)+r2(4)); - r = [left bot right-left top-bot]; - else - r = r1; - end - - function r = LocalAxesTightBoundingBox(axesR, a) - if strcmp(get(a,'handlevisibility'),'on') - r = get(a,'position'); - else - r = []; - end - atext = findall(a,'type','text','visible','on'); - if ~isempty(atext) - set(atext,'units','points'); - res=LocalGetAsCell(atext,'extent'); - for n=1:length(atext) - r = LocalUnionRect(r,res{n}); - end - end - if strcmp(get(a,'visible'),'on') - r = LocalUnionRect(r,[0 0 axesR(3:4)]); - oldunits = get(a,'fontunits'); - set(a,'fontunits','points'); - label = text(0,0,'','parent',a,... - 'units','points',... - 'fontsize',get(a,'fontsize'),... - 'fontname',get(a,'fontname'),... - 'fontweight',get(a,'fontweight'),... - 'fontangle',get(a,'fontangle'),... - 'visible','off'); - fs = get(a,'fontsize'); - - % handle y axis tick labels - ry = [0 0 0 axesR(4)]; - ylabs = get(a,'yticklabels'); - yticks = get(a,'ytick'); - maxw = 0; - if ~isempty(ylabs) - for n=1:size(ylabs,1) - if strcmp(get(a,'yscale'),'log') - set(label,'string',['10^' ylabs(n,:)]); - else - set(label,'string',ylabs(n,:)); - end - ext = get(label,'extent'); - maxw = max(maxw,ext(3)); - end - if strcmp(get(a,'yaxislocation'),'left') - ry(1) = -(maxw+5); - else - ry(1) = axesR(3); - end - ry(2) = -ext(4)/2; - ry(3) = maxw+5; - ry(4) = ry(4) + ext(4); - if ~isempty(yticks) - if ~strcmp(get(a,'yscale'),'log') & ... - ((str2num(ylabs(1,:)) ~= yticks(1)) | ... - (str2num(ylabs(end,:)) ~= yticks(end))) - set(label,'string','10^1'); - ext = get(label,'extent'); - if strcmp(get(a,'xaxislocation'),'bottom') - ry(4) = ry(4) + ext(4); - end - end - end - r = LocalUnionRect(r,ry); - end - - % handle x axis tick labels - rx = [0 0 axesR(3) 0]; - xlabs = get(a,'xticklabels'); - xticks = get(a,'xtick'); - if ~isempty(xlabs) - if strcmp(get(a,'xscale'),'log') - set(label,'string',['10^' xlabs(1,:)]); - else - set(label,'string',xlabs(1,:)); - end - ext1 = get(label,'extent'); - rx(1) = -ext1(3)/2; - if strcmp(get(a,'xscale'),'log') - set(label,'string',['10^' xlabs(size(xlabs,1),:)]); - else - set(label,'string',xlabs(size(xlabs,1),:)); - end - ext2 = get(label,'extent'); - rx(4) = max(ext1(4),ext2(4)); - rx(2) = -rx(4); - rx(3) = axesR(3) + (ext2(3) + ext1(3))/2; - if strcmp(get(a,'xaxislocation'),'top') - rx(2) = rx(2) + axesR(4); - end - if ~isempty(xticks) - if ~strcmp(get(a,'xscale'),'log') & ... - ((str2num(xlabs(1,:)) ~= xticks(1)) | ... - (str2num(xlabs(end,:)) ~= xticks(end))) - set(label,'string','10^1'); - ext = get(label,'extent'); - if strcmp(get(a,'xaxislocation'),'bottom') - rx(4) = rx(4) + ext(4)+5; - rx(2) = rx(2) - ext(4)-5; - else - rx(4) = rx(4) + ext(4)+5 + axesR(4); - rx(2) = rx(2) - ext(4)-5 - axesR(4); - end - end - end - r = LocalUnionRect(r,rx); - end - set(a,'fontunits',oldunits); - delete(label); - end - - function c = LocalManualAxesMode(old, allAxes, base) - xs = ['X' base]; - ys = ['Y' base]; - zs = ['Z' base]; - xlog = LocalGetAsCell(allAxes,'xscale'); - ylog = LocalGetAsCell(allAxes,'yscale'); - zlog = LocalGetAsCell(allAxes,'zscale'); - nonlogxflag = logical([]); - nonlogyflag = logical([]); - nonlogzflag = logical([]); - for k = 1:length(xlog) - nonlogxflag(k) = logical(~strcmp(xlog{k},'log')); - nonlogyflag(k) = logical(~strcmp(ylog{k},'log')); - nonlogzflag(k) = logical(~strcmp(zlog{k},'log')); - end - allNonLogXAxes = allAxes(nonlogxflag); - allNonLogYAxes = allAxes(nonlogyflag); - allNonLogZAxes = allAxes(nonlogzflag); - oldXMode = LocalGetAsCell(allNonLogXAxes,xs); - oldYMode = LocalGetAsCell(allNonLogYAxes,ys); - oldZMode = LocalGetAsCell(allNonLogZAxes,zs); - old = LocalPushOldData(old, allNonLogXAxes, {xs}, oldXMode); - old = LocalPushOldData(old, allNonLogYAxes, {ys}, oldYMode); - old = LocalPushOldData(old, allNonLogZAxes, {zs}, oldZMode); - set(allNonLogXAxes,xs,'manual'); - set(allNonLogYAxes,ys,'manual'); - set(allNonLogZAxes,zs,'manual'); - c = old; - - function val = LocalCheckAuto(val, auto) - if ischar(val) & strcmp(val,'auto') - val = auto; - end diff --git a/experiment/simulation/backend/exp_weighted_matching/initMlp.m b/experiment/simulation/backend/exp_weighted_matching/initMlp.m deleted file mode 100755 index c519223..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/initMlp.m +++ /dev/null @@ -1,58 +0,0 @@ -function [X, X1, X2, w, W, P, T, N, d, r, eta0, etaT, indexArray, currentSampleIndex, trainingSample, currentIterationIndex, globalCount, updateFlag] = initMlp(numSamplesPerClass, numIterations) - P = numSamplesPerClass; - - % Generate samples and initialize class index. - x1 = rand(P,2); - x2 = rand(P,2); - - xoffset = 1.4; - yoffset = 0.8; - x2 = x2 + repmat([xoffset,yoffset],P,1); - - X(1:P,1:2) = x1; - X(1:P,3) = repmat(1,P,1); - - X(P+1:2*P,1:2) = x2; - X(P+1:2*P,3) = repmat(2,P,1); - - T = numIterations; - - [N,r] = size(X); - d = r-1; - - % Normalize data. - Xmax = max(max(abs(X(:,1:d)))); - X(:,1:d) = X(:,1:d)/Xmax; - - % Identify elements of class-1 and class-2. - i1 = find(X(:,r) == 1); - i2 = find(X(:,r) == 2); - - X1 = X(i1,1:d); - X2 = X(i2,1:d); - - % Learning rate. - eta0 = 0.1; - etaT = eta0; - - % Initialize weights. - wtmp = rand(1,d); - x = X1(1,1); - y = X1(1,2); - %theta = W(1)*x + W(2)*y; - theta = rand(1); - w = [theta (wtmp(:))']'; - w = w(:); - - % Make provision for storing weights for all iterations. - W(:,1) = w; - W(:,2) = w; - - % Generate indices from 1 to N, but in a random fashion. - indexArray = randperm(N); - - currentSampleIndex =1; - trainingSample = X(indexArray(currentSampleIndex), 1:d); - currentIterationIndex =1; - globalCount = 1; - updateFlag = 1; diff --git a/experiment/simulation/backend/exp_weighted_matching/init_wmp.m b/experiment/simulation/backend/exp_weighted_matching/init_wmp.m deleted file mode 100755 index b1ef452..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/init_wmp.m +++ /dev/null @@ -1,30 +0,0 @@ -function init_wmp(points, filepath) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - %addpath ~/svl-lib/matlib/Tools-fromnet/exportfig/ - - Nnodes=length(points); - global filename; - filename = filepath; - - %xyminmax = min_max(points'); - figure; - %applytofig(gcf,'width',10,'height',8); - plot(points(:,1),points(:,2),'o','markersize',30,'linewidth',6); - %xlim([xyminmax(1,1)-1,xyminmax(1,2)+1]); - %ylim([xyminmax(2,1)-1,xyminmax(2,2)+1]); - - xymin=min(min(points))-1; - xymax=max(max(points))+1; - xlim([xymin xymax]); - ylim([xymin xymax]); - - for i=1:Nnodes;text(points(i,1),points(i,2)+.7,num2str(i),'fontsize',20);end - - print(strcat(filename, "-1.png")) - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/initgraph.m b/experiment/simulation/backend/exp_weighted_matching/initgraph.m deleted file mode 100755 index 81e8f42..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/initgraph.m +++ /dev/null @@ -1,12 +0,0 @@ -function graph = initgraph(Nnodes,edges) - disp(Nnodes); - disp(edges); - - A = sparse(edges(:,1),edges(:,2),1,Nnodes,Nnodes); - graph = full(A); - - plotgraph(graph); - - print tmp/input.png - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/previewfig.m b/experiment/simulation/backend/exp_weighted_matching/previewfig.m deleted file mode 100755 index 5039a57..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/previewfig.m +++ /dev/null @@ -1,49 +0,0 @@ -function f = previewfig(h,varargin) - %PREVIEWFIG Preview a figure to be exported using EXPORTFIG. - % F = PREVIEWFIG(H) creates a preview of H with the default - % EXPORTFIG options and returns the preview's figure handle in F. - % F = PREVIEWFIG(H,OPTIONS) creates a preview with OPTIONS as - % described in EXPORTFIG. - % PREVIEWFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) creates a preview - % with the specified parameter-value pairs to H as described in - % EXPORTFIG. - % - % See also EXPORTFIG, APPLYTOFIG, RESTOREFIG. - - % Copyright 2000-2009 The MathWorks, Inc. - % Email bug reports and comments to bhinkle@mathworks.com - - filename = [tempname, '.png']; - args = {'resolution',0,'format','png'}; - if nargin > 1 - exportfig(h, filename, varargin{:}, args{:}); - else - exportfig(h, filename, args{:}); - end - - X = imread(filename,'png'); - height = size(X,1); - width = size(X,2); - delete(filename); - f = figure( 'Name', 'Preview', ... - 'Menubar', 'none', ... - 'NumberTitle', 'off', ... - 'Visible', 'off'); - image(X); - axis image; - ax = findobj(f, 'type', 'axes'); - axesPos = [0 0 width height]; - set(ax, 'Units', 'pixels', ... - 'Position', axesPos, ... - 'Visible', 'off'); - figPos = get(f,'Position'); - rootSize = get(0,'ScreenSize'); - figPos(3:4) = axesPos(3:4); - if figPos(1) + figPos(3) > rootSize(3) - figPos(1) = rootSize(3) - figPos(3) - 50; - end - if figPos(2) + figPos(4) > rootSize(4) - figPos(2) = rootSize(4) - figPos(4) - 50; - end - set(f, 'Position',figPos, ... - 'Visible', 'on'); diff --git a/experiment/simulation/backend/exp_weighted_matching/restorefig.m b/experiment/simulation/backend/exp_weighted_matching/restorefig.m deleted file mode 100755 index b030a01..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/restorefig.m +++ /dev/null @@ -1,19 +0,0 @@ -function restorefig(h,old) - %RESTOREFIG Restore a figure's properties - % RESTOREFIG(H,OLD) restores the properties of H specified in - % OLD. The state-difference structure OLD is the output of the - % function APPLYTOFIG. Deleting object handles after the call to - % APPLYFIG might cause undesired behavior. - % - % See also EXPORTFIG, PREVIEWFIG, APPLYTOFIG. - - % Copyright 2000-2009 The MathWorks, Inc. - - for n=1:length(old.objs) - try - if ~iscell(old.values{n}) & iscell(old.prop{n}) - old.values{n} = {old.values{n}}; - end - set(old.objs{n}, old.prop{n}, old.values{n}); - end - end diff --git a/experiment/simulation/backend/exp_weighted_matching/weightedmatchillustration.m b/experiment/simulation/backend/exp_weighted_matching/weightedmatchillustration.m deleted file mode 100755 index 4100427..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/weightedmatchillustration.m +++ /dev/null @@ -1,85 +0,0 @@ -function weightedmatchillustration() - addpath ~/svl-lib/matlib/Tools-fromnet/exportfig/ - points=[1 5;3 8;5 1;8 3]; - - N=length(points); - d=zeros(N,N); - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - mpx(i,j)=(points(i,1)+points(j,1))/2; - mpy(i,j)=(points(i,2)+points(j,2))/2; - end - end - - g = zeros(N,N); - drawweightedgraph(g,points); - saveas(gcf,'figures/prob.tiff'); - - - g1 = [ - 0 1 1 1; - 0 0 1 1; - 0 0 0 1; - 0 0 0 0; - ]; - drawweightedgraph(g1,points,d,mpx,mpy) - saveas(gcf,'figures/wgraph.tiff'); - - g2 = zeros(N,N); - g2(1,2)=1;g2(3,4)=1; - drawweightedgraph(g2,points,d,mpx,mpy) - saveas(gcf,'figures/sol1.tiff'); - - - g2 = zeros(N,N); - g2(1,3)=1;g2(2,4)=1; - drawweightedgraph(g2,points,d,mpx,mpy) - saveas(gcf,'figures/sol2.tiff'); - - g2 = zeros(N,N); - g2(1,4)=1;g2(2,3)=1; - drawweightedgraph(g2,points,d,mpx,mpy) - saveas(gcf,'figures/sol3.tiff'); - - - return; - - - function drawweightedgraph(g,nodes,d,mpx,mpy) - - N=length(nodes); - figure; - applytofig(gcf,'width',10,'height',8); - gplot(g,nodes);hold on; - plot(nodes(:,1),nodes(:,2),'o','markersize',20); - - - %xlim([xyminmax(1,1)-1,xyminmax(1,2)+1]); - %ylim([xyminmax(2,1)-1,xyminmax(2,2)+1]); - xymin=min(min(nodes))-1; - xymax=max(max(nodes))+1; - xlim([xymin xymax]); - ylim([xymin xymax]); - - for i=1:N;text(nodes(i,1),nodes(i,2)+.7,num2str(i));end - %for i=1:N;text(nodes(i,1)-.1,nodes(i,2),num2str(i));end - - if(exist('d')) - for i=1:N - for j=1:N - if(g(i,j)==1) - text(mpx(i,j)+.5,mpy(i,j)+.5,sprintf('%3.1f',d(i,j))); - end - end - end - end - - - lh=findall(gcf,'type','line'); - set(lh,'linewidth',4); - ah=findall(gcf,'type','axes'); - th=findall(gcf,'type','text'); - set([ah;th],'fontsize',12,'fontweight','bold'); - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/weightedmatching_det.m b/experiment/simulation/backend/exp_weighted_matching/weightedmatching_det.m deleted file mode 100755 index 7b13cf0..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/weightedmatching_det.m +++ /dev/null @@ -1,63 +0,0 @@ -function finalstate = wmp_det(points,initstate) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - - N=length(points); - d=zeros(N,N); - unit=[]; - th=[]; - k=1; - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - unit(k,:)=[i j]; - th=[th; d(i,j)]; - k=k+1; - end - end - d=d+d'; - - - % The nodes are (i,j): 12, 13, 14, 23, 24, 34 - - M=nchoosek(N,2); - gamma=max(max(d))/(M/2); - W = zeros(M,M); - - for i=1:M - for j=i+1:M - if(any(~[unit(i,:)-unit(j,:) unit(i,[2 1])-unit(j,:)])) - W(i,j)=-gamma; - end - end - end - - W = W + W'; - - th=th-gamma; - - % Random initialization - %state = (rand(M,1)-0.5)>0; - %state=[0 1 1 0 0 0]' - state=initstate; - disp(state') - tempstate = zeros(M,1); - stateseq=[zeros(M,2) state]; - k=3; - while(norm(tempstate-state) ~= 0 & norm(stateseq(:,k)-stateseq(:,k-2))~=0 | k<10) - tempstate=state; - state=W*state+th; - disp(state') - state=state>0; - disp(state') - stateseq=[stateseq state]; - k=k+1; - %pause; - end - finalstate=state; - - return; diff --git a/experiment/simulation/backend/exp_weighted_matching/weightedmatching_sto.m b/experiment/simulation/backend/exp_weighted_matching/weightedmatching_sto.m deleted file mode 100755 index bf5a1cc..0000000 --- a/experiment/simulation/backend/exp_weighted_matching/weightedmatching_sto.m +++ /dev/null @@ -1,87 +0,0 @@ -function FinalState = weightedmatching_sto(points,InitState) - %%%%%%%%% - % Ex1: points=[1 1;3 3;0 4;2 6]; - % The network yields solution only for certain initial states. For other - % init states, the network oscillates or gets stuck at some local minima. - % validinitstates=[5 6 7 9 10 11 13 14 15 21 25 29 37 41 45]; - %%%%%%%%% - - %points=[1 1;3 3;0 4;2 6]; - N=length(points); - d=zeros(N,N); - unit=[]; - th=[]; - k=1; - for i=1:N - for j=i+1:N - d(i,j)=norm(points(i,:)-points(j,:)); - unit(k,:)=[i j]; - th=[th; d(i,j)]; - k=k+1; - end - end - d=d+d'; - - - % The nodes are (i,j): 12, 13, 14, 23, 24, 34 - - M=nchoosek(N,2); - gamma=max(max(d))/(M/2); - W = zeros(M,M); - - for i=1:M - for j=i+1:M - if(any(~[unit(i,:)-unit(j,:) unit(i,[2 1])-unit(j,:)])) - W(i,j)=-gamma; - end - end - end - - W = W + W'; - - th=th-gamma; - th=th(:); - - % Random initialization - %state = (rand(M,1)-0.5)>0; - %state=[0 1 1 0 0 0]' - State=InitState(:); - disp(State') - - T=1; - dT=0.01; - - while(T>0.1) - PresentAvgState=rand(1,6); - TempAvgState=rand(1,6); - T=T-dT; - while(norm(PresentAvgState-TempAvgState) ~= 0) - TempAvgState=PresentAvgState; - for i=1:100 - TempState=State; - State=W*State+th; - State=squash(State,T); - PresentState(:,i)=State; - end - PartitionFn=0; - E=Present*W*Present'; - Energy - - end - - tempstate = zeros(M,1); - stateseq=[zeros(M,2) state]; - k=3; - while(norm(tempstate-state) ~= 0 & norm(stateseq(:,k)-stateseq(:,k-2))~=0 | k<10) - tempstate=state; - state=W*state+th; - disp(state') - state=state>0; - disp(state') - stateseq=[stateseq state]; - k=k+1; - %pause; - end - finalstate=state; - - return; diff --git a/experiment/simulation/backend/requirements.txt b/experiment/simulation/backend/requirements.txt deleted file mode 100644 index 03df14b..0000000 --- a/experiment/simulation/backend/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -click==7.1.1 -Flask==1.1.2 -Flask-Cors==3.0.8 -itsdangerous==1.1.0 -Jinja2==2.11.1 -MarkupSafe==1.1.1 -six==1.14.0 -Werkzeug==1.0.1 diff --git a/experiment/simulation/backend/server.py b/experiment/simulation/backend/server.py deleted file mode 100644 index f01b2d4..0000000 --- a/experiment/simulation/backend/server.py +++ /dev/null @@ -1,141 +0,0 @@ -import uuid - -from flask import Flask, request, abort -from flask_cors import CORS - -import exp_optimization -import exp_weighted_matching -from utils import * - -app = Flask(__name__) -CORS(app) - - -def get_args(exp_name, arg_dict): - order = [] - - if exp_name == "perceptron": - order = [ - "Nsamples", - "Niterns", - "sample", - "itern", - "Nsamplestep", - "NIstep", - "probtype", - ] - elif exp_name == "mlfnn": - order = [ - "isTrain", - "numberOfBits", - "numberOfhiddenNodes", - ] - elif exp_name == "clnn": - order = [ - "type", - "inputDim", - "numDataPoints", - "region", - "numIterations", - "NIstep", - ] - elif exp_name == "tsp": - order = [ - "Ncities", - "Nnodes", - "Niterns", - "city", - "itern", - "NCstep", - "NIstep", - ] - - arg_list = [] - - for arg in order: - arg_list.append(arg_dict[arg]) - - return ", ".join(arg_list) - - -@app.route("/get_token", methods=["GET"]) -def token(): - """ - Returns a token which will be used for all transactions with this server - """ - uid = str(uuid.uuid4()) - return uid - - -@app.route("/exp-", methods=["POST"]) -def exp(num): - known_exps = ["perceptron", "mlfnn", "clnn", "tsp"] - - if num not in known_exps: - abort(404) - - uid = request.headers.get("token") - - if uid is None: - # https://stackoverflow.com/a/4301901 - return "Token missing", 403 - - data = request.get_json() - try: - args = get_args(num, data) - except Exception as e: - print(e) - return "Invalid data for given experiment", 400 - - clear_png(num, uid) - res = run_octave(num=num, arg=args, token=uid) - - if res: - return res - - images = read_all_pngs(num, uid) - - result = "" - if num == 4 and data["isTrain"] == "0" and int(data["numberOfBits"]) > -1: - result = read_result(num, uid) - - return jsonify(images=images, result=result) - - -@app.route("/exp--", methods=["POST"]) -def exp_part(num, part): - uid = request.headers.get("token") - - if uid is None: - # https://stackoverflow.com/a/4301901 - return "Token missing", 403 - - data = request.get_json() - - runner = None - if num == "optimization": - if part not in exp_optimization.num_map: - abort(404) - - runner = exp_optimization - - if num == "weighted_matching": - if part not in exp_weighted_matching.num_map: - abort(404) - - runner = exp_weighted_matching - - if not runner: - abort(404) - - try: - data["token"] = uid - res = runner.runexp(data, part) - return res - except Exception: - return "Invalid data for given experiment", 400 - - - -if __name__ == "__main__": - app.run(host="0.0.0.0", port=4647, debug=True) diff --git a/experiment/simulation/backend/swagger.yaml b/experiment/simulation/backend/swagger.yaml deleted file mode 100644 index 885f2d9..0000000 --- a/experiment/simulation/backend/swagger.yaml +++ /dev/null @@ -1,114 +0,0 @@ -openapi: 3.0.0 -info: - title: vlabs ANN API - description: The API for Artificial Neural Networks lab - version: 1.0.0 -paths: - /get_token: - get: - summary: Returns a token which is used to used to uniquely identify users - responses: - "200": - description: The token to return - content: - "application/json": - schema: - type: object - properties: - token: - type: string - example: 076d27ee-1ce7-4726-8458-b014b2428150 - "/exp{num}": - post: - summary: Performs the tasks related to that experiment and returns generated - images - parameters: - - in: path - name: num - required: true - description: The experiment number [one of {3, 4, 7, 8}] - schema: - type: integer - responses: - "200": - description: The results (images/tables) for that experiment - content: - "application/json": - schema: - type: object - properties: - images: - type: array - items: - type: string - result: - type: string - "403": - description: Token missing - "404": - description: This experiment number is not supported by this API - "500": - description: Octave threw an error - content: - "application/json": - schema: - type: object - properties: - message: - type: string - example: Octave didn't work - error: - type: string - example: error on line 13 - "/exp{num}-{part}": - post: - summary: Performs the tasks related to that experiment, part and returns - generated images - parameters: - - in: path - name: num - required: true - description: The experiment number - schema: - type: integer - minimum: 9 - maximum: 10 - - in: path - name: part - required: true - description: The part of that experiment - schema: - type: integer - responses: - "200": - description: The results (images/tables) for that experiment - content: - "application/json": - schema: - type: object - properties: - images: - type: array - items: - type: string - result: - type: string - "403": - description: Token missing - "404": - description: This experiment number/part combination is not supported by this API - "500": - description: Octave threw an error - content: - "application/json": - schema: - type: object - properties: - message: - type: string - example: Octave didn't work - error: - type: string - example: error on line 13 -servers: - - url: http://localhost:4647/ diff --git a/experiment/simulation/backend/utils.py b/experiment/simulation/backend/utils.py deleted file mode 100644 index 0ee2a34..0000000 --- a/experiment/simulation/backend/utils.py +++ /dev/null @@ -1,85 +0,0 @@ -import subprocess -import base64 -import glob - -from flask import jsonify - -def get_exp_base(num): - return f"exp_{num}" - -def get_basepath(num, token): - return f"{get_exp_base(num)}/{token}" - - -def clear_files(num, token, clear_res=True): - base = get_exp_base(num) - files = glob.glob(f"{base}/{token}*.png") - if clear_res: - files.append(f"{base}/{token}-result.txt") - - if len(files) > 0: - subprocess.run(["rm", *files]) - - -def run_octave(num, method="runexp", arg="", token=""): - runstr = f"{method}({arg}, '{token}')" - print(runstr) - - base = get_exp_base(num) - arg = f"cd {base}; pkg load nnet; {runstr}" - proc = subprocess.run( - ["octave", "--eval", arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - - if proc.returncode != 0: - print(proc.stderr.decode("utf-8")) - return ( - jsonify(message="Octave didn't work", error=proc.stderr.decode("utf-8")), - 500, - ) - - return None - - -def clear_png(num, token): - clear_files(num, token, clear_res=False) - - -def get_png(path): - try: - with open(f"{path}.png", "rb") as img: - img_b64 = base64.b64encode(img.read()).decode("utf-8") - return img_b64 - except FileNotFoundError: - print(f"File {path}.png not found") - - return None - - -def read_all_pngs(num, token, cnt=2): - basepath = get_basepath(num, token) - images = [] - - fil = get_png(basepath) - if fil: - images.append(fil) - - for i in range(1, cnt + 1): - fil = get_png(f"{basepath}-{i}") - if fil: - images.append(fil) - - return images - - -def read_result(num, token): - basepath = get_basepath(num, token) - try: - with open(f"{basepath}-result.txt", "r") as res: - result = res.read() - except FileNotFoundError: - result = "" - print("Result not ready") - result = result.replace("\n", "
") - - return result diff --git a/experiment/simulation/backend/venv/bin/activate b/experiment/simulation/backend/venv/bin/activate deleted file mode 100644 index d8d7433..0000000 --- a/experiment/simulation/backend/venv/bin/activate +++ /dev/null @@ -1,84 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - - -if [ "${BASH_SOURCE-}" = "$0" ]; then - echo "You must source this script: \$ source $0" >&2 - exit 33 -fi - -deactivate () { - unset -f pydoc >/dev/null 2>&1 - - # reset old environment variables - # ! [ -z ${VAR+_} ] returns true if VAR is declared at all - if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then - PATH="$_OLD_VIRTUAL_PATH" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then - PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null - fi - - if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then - PS1="$_OLD_VIRTUAL_PS1" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "${1-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -if ! [ -z "${PYTHONHOME+_}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1-}" - if [ "x" != x ] ; then - PS1="${PS1-}" - else - PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}" - fi - export PS1 -fi - -# Make sure to unalias pydoc if it's already there -alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true - -pydoc () { - python -m pydoc "$@" -} - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null -fi diff --git a/experiment/simulation/backend/venv/bin/activate.csh b/experiment/simulation/backend/venv/bin/activate.csh deleted file mode 100644 index d5bc0e1..0000000 --- a/experiment/simulation/backend/venv/bin/activate.csh +++ /dev/null @@ -1,55 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . - -set newline='\ -' - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv" - -set _OLD_VIRTUAL_PATH="$PATH:q" -setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q" - - - -if ("" != "") then - set env_name = "" -else - set env_name = '('"$VIRTUAL_ENV:t:q"') ' -endif - -if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then - if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then - set do_prompt = "1" - else - set do_prompt = "0" - endif -else - set do_prompt = "1" -endif - -if ( $do_prompt == "1" ) then - # Could be in a non-interactive environment, - # in which case, $prompt is undefined and we wouldn't - # care about the prompt anyway. - if ( $?prompt ) then - set _OLD_VIRTUAL_PROMPT="$prompt:q" - if ( "$prompt:q" =~ *"$newline:q"* ) then - : - else - set prompt = "$env_name:q$prompt:q" - endif - endif -endif - -unset env_name -unset do_prompt - -alias pydoc python -m pydoc - -rehash diff --git a/experiment/simulation/backend/venv/bin/activate.fish b/experiment/simulation/backend/venv/bin/activate.fish deleted file mode 100644 index b1e6a80..0000000 --- a/experiment/simulation/backend/venv/bin/activate.fish +++ /dev/null @@ -1,102 +0,0 @@ -# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. -# Do not run it directly. - -function _bashify_path -d "Converts a fish path to something bash can recognize" - set fishy_path $argv - set bashy_path $fishy_path[1] - for path_part in $fishy_path[2..-1] - set bashy_path "$bashy_path:$path_part" - end - echo $bashy_path -end - -function _fishify_path -d "Converts a bash path to something fish can recognize" - echo $argv | tr ':' '\n' -end - -function deactivate -d 'Exit virtualenv mode and return to the normal environment.' - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling - if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 - set -gx PATH (_fishify_path $_OLD_VIRTUAL_PATH) - else - set -gx PATH $_OLD_VIRTUAL_PATH - end - set -e _OLD_VIRTUAL_PATH - end - - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - and functions -q _old_fish_prompt - # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. - set -l fish_function_path - - # Erase virtualenv's `fish_prompt` and restore the original. - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - end - - set -e VIRTUAL_ENV - - if test "$argv[1]" != 'nondestructive' - # Self-destruct! - functions -e pydoc - functions -e deactivate - functions -e _bashify_path - functions -e _fishify_path - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv" - -# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling -if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 - set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH) -else - set -gx _OLD_VIRTUAL_PATH $PATH -end -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# Unset `$PYTHONHOME` if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -function pydoc - python -m pydoc $argv -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # Copy the current `fish_prompt` function as `_old_fish_prompt`. - functions -c fish_prompt _old_fish_prompt - - function fish_prompt - # Save the current $status, for fish_prompts that display it. - set -l old_status $status - - # Prompt override provided? - # If not, just prepend the environment name. - if test -n "" - printf '%s%s' "" (set_color normal) - else - printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") - end - - # Restore the original $status - echo "exit $old_status" | source - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end diff --git a/experiment/simulation/backend/venv/bin/activate.ps1 b/experiment/simulation/backend/venv/bin/activate.ps1 deleted file mode 100644 index 95504d3..0000000 --- a/experiment/simulation/backend/venv/bin/activate.ps1 +++ /dev/null @@ -1,60 +0,0 @@ -$script:THIS_PATH = $myinvocation.mycommand.path -$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent - -function global:deactivate([switch] $NonDestructive) { - if (Test-Path variable:_OLD_VIRTUAL_PATH) { - $env:PATH = $variable:_OLD_VIRTUAL_PATH - Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global - } - - if (Test-Path function:_old_virtual_prompt) { - $function:prompt = $function:_old_virtual_prompt - Remove-Item function:\_old_virtual_prompt - } - - if ($env:VIRTUAL_ENV) { - Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue - } - - if (!$NonDestructive) { - # Self destruct! - Remove-Item function:deactivate - Remove-Item function:pydoc - } -} - -function global:pydoc { - python -m pydoc $args -} - -# unset irrelevant variables -deactivate -nondestructive - -$VIRTUAL_ENV = $BASE_DIR -$env:VIRTUAL_ENV = $VIRTUAL_ENV - -New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH - -$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH -if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) { - function global:_old_virtual_prompt { - "" - } - $function:_old_virtual_prompt = $function:prompt - - if ("" -ne "") { - function global:prompt { - # Add the custom prefix to the existing prompt - $previous_prompt_value = & $function:_old_virtual_prompt - ("" + $previous_prompt_value) - } - } - else { - function global:prompt { - # Add a prefix to the current prompt, but don't discard it. - $previous_prompt_value = & $function:_old_virtual_prompt - $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) " - ($new_prompt_value + $previous_prompt_value) - } - } -} diff --git a/experiment/simulation/backend/venv/bin/activate.xsh b/experiment/simulation/backend/venv/bin/activate.xsh deleted file mode 100644 index b8fbab4..0000000 --- a/experiment/simulation/backend/venv/bin/activate.xsh +++ /dev/null @@ -1,46 +0,0 @@ -"""Xonsh activate script for virtualenv""" -from xonsh.tools import get_sep as _get_sep - -def _deactivate(args): - if "pydoc" in aliases: - del aliases["pydoc"] - - if ${...}.get("_OLD_VIRTUAL_PATH", ""): - $PATH = $_OLD_VIRTUAL_PATH - del $_OLD_VIRTUAL_PATH - - if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""): - $PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME - del $_OLD_VIRTUAL_PYTHONHOME - - if "VIRTUAL_ENV" in ${...}: - del $VIRTUAL_ENV - - if "VIRTUAL_ENV_PROMPT" in ${...}: - del $VIRTUAL_ENV_PROMPT - - if "nondestructive" not in args: - # Self destruct! - del aliases["deactivate"] - - -# unset irrelevant variables -_deactivate(["nondestructive"]) -aliases["deactivate"] = _deactivate - -$VIRTUAL_ENV = r"/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv" - -$_OLD_VIRTUAL_PATH = $PATH -$PATH = $PATH[:] -$PATH.add($VIRTUAL_ENV + _get_sep() + "bin", front=True, replace=True) - -if ${...}.get("PYTHONHOME", ""): - # unset PYTHONHOME if set - $_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME - del $PYTHONHOME - -$VIRTUAL_ENV_PROMPT = "" -if not $VIRTUAL_ENV_PROMPT: - del $VIRTUAL_ENV_PROMPT - -aliases["pydoc"] = ["python", "-m", "pydoc"] diff --git a/experiment/simulation/backend/venv/bin/activate_this.py b/experiment/simulation/backend/venv/bin/activate_this.py deleted file mode 100644 index aa96457..0000000 --- a/experiment/simulation/backend/venv/bin/activate_this.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Activate virtualenv for current interpreter: - -Use exec(open(this_file).read(), {'__file__': this_file}). - -This can be used when you must use an existing Python interpreter, not the virtualenv bin/python. -""" -import os -import site -import sys - -try: - __file__ -except NameError: - raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))") - -# prepend bin to PATH (this file is inside the bin directory) -bin_dir = os.path.dirname(os.path.abspath(__file__)) -os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) - -base = os.path.dirname(bin_dir) - -# virtual env is right above bin directory -os.environ["VIRTUAL_ENV"] = base - -# add the virtual environments site-package to the host python import mechanism -IS_PYPY = hasattr(sys, "pypy_version_info") -IS_JYTHON = sys.platform.startswith("java") -if IS_JYTHON: - site_packages = os.path.join(base, "Lib", "site-packages") -elif IS_PYPY: - site_packages = os.path.join(base, "site-packages") -else: - IS_WIN = sys.platform == "win32" - if IS_WIN: - site_packages = os.path.join(base, "Lib", "site-packages") - else: - site_packages = os.path.join(base, "lib", "python{}.{}".format(*sys.version_info), "site-packages") - -prev = set(sys.path) -site.addsitedir(site_packages) -sys.real_prefix = sys.prefix -sys.prefix = base - -# Move the added items to the front of the path, in place -new = list(sys.path) -sys.path[:] = [i for i in new if i not in prev] + [i for i in new if i in prev] diff --git a/experiment/simulation/backend/venv/bin/easy_install b/experiment/simulation/backend/venv/bin/easy_install deleted file mode 100755 index 692ce3f..0000000 --- a/experiment/simulation/backend/venv/bin/easy_install +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from setuptools.command.easy_install import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/easy_install-3.7 b/experiment/simulation/backend/venv/bin/easy_install-3.7 deleted file mode 100755 index 692ce3f..0000000 --- a/experiment/simulation/backend/venv/bin/easy_install-3.7 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from setuptools.command.easy_install import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/flask b/experiment/simulation/backend/venv/bin/flask deleted file mode 100755 index e64dcdd..0000000 --- a/experiment/simulation/backend/venv/bin/flask +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from flask.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/pip b/experiment/simulation/backend/venv/bin/pip deleted file mode 100755 index ff72687..0000000 --- a/experiment/simulation/backend/venv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/pip3 b/experiment/simulation/backend/venv/bin/pip3 deleted file mode 100755 index ff72687..0000000 --- a/experiment/simulation/backend/venv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/pip3.7 b/experiment/simulation/backend/venv/bin/pip3.7 deleted file mode 100755 index ff72687..0000000 --- a/experiment/simulation/backend/venv/bin/pip3.7 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/bin/python b/experiment/simulation/backend/venv/bin/python deleted file mode 120000 index 940bee3..0000000 --- a/experiment/simulation/backend/venv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3.7 \ No newline at end of file diff --git a/experiment/simulation/backend/venv/bin/python-config b/experiment/simulation/backend/venv/bin/python-config deleted file mode 100755 index e4ece92..0000000 --- a/experiment/simulation/backend/venv/bin/python-config +++ /dev/null @@ -1,78 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python - -import sys -import getopt -import sysconfig - -valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', - 'ldflags', 'help'] - -if sys.version_info >= (3, 2): - valid_opts.insert(-1, 'extension-suffix') - valid_opts.append('abiflags') -if sys.version_info >= (3, 3): - valid_opts.append('configdir') - - -def exit_with_usage(code=1): - sys.stderr.write("Usage: {0} [{1}]\n".format( - sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) - sys.exit(code) - -try: - opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) -except getopt.error: - exit_with_usage() - -if not opts: - exit_with_usage() - -pyver = sysconfig.get_config_var('VERSION') -getvar = sysconfig.get_config_var - -opt_flags = [flag for (flag, val) in opts] - -if '--help' in opt_flags: - exit_with_usage(code=0) - -for opt in opt_flags: - if opt == '--prefix': - print(sysconfig.get_config_var('prefix')) - - elif opt == '--exec-prefix': - print(sysconfig.get_config_var('exec_prefix')) - - elif opt in ('--includes', '--cflags'): - flags = ['-I' + sysconfig.get_path('include'), - '-I' + sysconfig.get_path('platinclude')] - if opt == '--cflags': - flags.extend(getvar('CFLAGS').split()) - print(' '.join(flags)) - - elif opt in ('--libs', '--ldflags'): - abiflags = getattr(sys, 'abiflags', '') - libs = ['-lpython' + pyver + abiflags] - libs += getvar('LIBS').split() - libs += getvar('SYSLIBS').split() - # add the prefix/lib/pythonX.Y/config dir, but only if there is no - # shared library in prefix/lib/. - if opt == '--ldflags': - if not getvar('Py_ENABLE_SHARED'): - libs.insert(0, '-L' + getvar('LIBPL')) - if not getvar('PYTHONFRAMEWORK'): - libs.extend(getvar('LINKFORSHARED').split()) - print(' '.join(libs)) - - elif opt == '--extension-suffix': - ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') - if ext_suffix is None: - ext_suffix = sysconfig.get_config_var('SO') - print(ext_suffix) - - elif opt == '--abiflags': - if not getattr(sys, 'abiflags', None): - exit_with_usage() - print(sys.abiflags) - - elif opt == '--configdir': - print(sysconfig.get_config_var('LIBPL')) diff --git a/experiment/simulation/backend/venv/bin/python3 b/experiment/simulation/backend/venv/bin/python3 deleted file mode 120000 index 940bee3..0000000 --- a/experiment/simulation/backend/venv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -python3.7 \ No newline at end of file diff --git a/experiment/simulation/backend/venv/bin/python3.7 b/experiment/simulation/backend/venv/bin/python3.7 deleted file mode 100755 index 29300bbdac14a5e1021bad3b8725b17a495d66a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14096 zcmeHOYit}>6~1f7&8CUh+h7;BiSSSrVxVQlGpgUz@83(tN|4puE)6O8wok?l-Q%VS^R*QAtT4#jM8fZ3sA{?uGEOrGBi@n!lr<`|65OFMW+_JHro|g{W`MkdLz=xZR!jqk{oD}N3j%-Y~(y`v>l-fYpEPNOe zBD4_l*gYec-~8bxubk=M`_dbauIs<}^5;Lh`KMRD{P^YHUU|N`_0{K_?|E+hqfdPO z@orX#7^Zt%Y-`t~$2Av#CAKcCwIWkGCT5&bts z@81hZ_X9eNRmS~<_#3it>ua6X;bSvyvF!AiADiU$*KMX0DMy*#rEGh2I%kiSoZLj| zNP$E)*;O}JaqY=m$x-&;&;dJNs1(LaRku(XI?z8+b_zqekqP!5pDa7#Z3nKaJ06^| zhn>>&0Y76f#%Ohl$1N$lkk7d}O2!Z*qg0kZexD?{Ba->=n|NYs) zzJ7bVx!v4Jg&@K{X;86Met6%+)a~Ra#!8jpO*yj zbPx!C$mj11^n5*H0qcKW3h6OdHY|knyx&2KAwBMCY+DNHu|`Wc_Qm+TeF{ry=Izsq^&n!d%b zXW4C|p$;)mL#^``S~`w$;(0;xpYi>7Rv5NivuaD$*{krRa$8zQ~*}2~D(-U##&|vLiW_Ymnc4jD3duQ01>pDs5PiMEh%Qap6 z#x>8g&c55|c648s_-yTO+1k~C+Upsw^%ZM&K4$It!_=R--VYtlJe)b4c_d?p=fLCf zm0CrLQ|!otDmI;rZQ8Il{wzKHvwkxj3xDxEe&SXG zYyCGltlvS$Y0`(^n{e(d9WT&0{yVyTiR3d4gNgR18}}xRxixzeoli9lBvQw3u@bvy z*X~cGoy6`;B9%#W_9cwIM0;N%*_Vj>@0-3#c`i|&@cSB4Y0?$Y70?yX70?yX70?yX z70?yX70?yn?y#x-kl<&zmJ~{ znP7kWnpgH^Y0AU1TS^!_D}GJv+;7YDRsi+h+jf!L1Oe#VElMJci#~1i@gg3G_kx?(grv$LP#dMvF$4 z8?B8!W{;Wb>fRDCN}1JS)vdU>5oMMfYG8d#nNHa)nB&frIWkqE2JKQ_RGGfPE;l!> zd|NSBEh;lV<5XuR19U5aUve?XnAt7;JE*FIk_jC*93Y{ zZ}zHa#4id1G{VlrN8|Z_HUFTsi}<)KVBk{{ zkNt{$g|zn)!!%e1?f+0Qf9gW1}ehj-gB zo+O4(5%DP_umDd5V*L~KhvGZL@b@-w-^TAZd|xH%4;lC)ifswSw3f+bxpt^K8zSU?3$8<3t=Vkh=ck+ DuAM66 diff --git a/experiment/simulation/backend/venv/bin/wheel b/experiment/simulation/backend/venv/bin/wheel deleted file mode 100755 index ccc0d17..0000000 --- a/experiment/simulation/backend/venv/bin/wheel +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/yog/iiit_h/assignments/dass/project/dass46/src/backend/venv/bin/python3.7 -# -*- coding: utf-8 -*- -import re -import sys -from wheel.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/include/python3.7m b/experiment/simulation/backend/venv/include/python3.7m deleted file mode 120000 index 4fe7f6c..0000000 --- a/experiment/simulation/backend/venv/include/python3.7m +++ /dev/null @@ -1 +0,0 @@ -/usr/include/python3.7m \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/LICENSE.txt b/experiment/simulation/backend/venv/lib/python3.7/LICENSE.txt deleted file mode 120000 index 6509a22..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/LICENSE.txt \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/__future__.py b/experiment/simulation/backend/venv/lib/python3.7/__future__.py deleted file mode 100644 index ce8bed7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/__future__.py +++ /dev/null @@ -1,146 +0,0 @@ -"""Record of phased-in incompatible language changes. - -Each line is of the form: - - FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease "," - CompilerFlag ")" - -where, normally, OptionalRelease < MandatoryRelease, and both are 5-tuples -of the same form as sys.version_info: - - (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int - PY_MINOR_VERSION, # the 1; an int - PY_MICRO_VERSION, # the 0; an int - PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string - PY_RELEASE_SERIAL # the 3; an int - ) - -OptionalRelease records the first release in which - - from __future__ import FeatureName - -was accepted. - -In the case of MandatoryReleases that have not yet occurred, -MandatoryRelease predicts the release in which the feature will become part -of the language. - -Else MandatoryRelease records when the feature became part of the language; -in releases at or after that, modules no longer need - - from __future__ import FeatureName - -to use the feature in question, but may continue to use such imports. - -MandatoryRelease may also be None, meaning that a planned feature got -dropped. - -Instances of class _Feature have two corresponding methods, -.getOptionalRelease() and .getMandatoryRelease(). - -CompilerFlag is the (bitfield) flag that should be passed in the fourth -argument to the builtin function compile() to enable the feature in -dynamically compiled code. This flag is stored in the .compiler_flag -attribute on _Future instances. These values must match the appropriate -#defines of CO_xxx flags in Include/compile.h. - -No feature line is ever to be deleted from this file. -""" - -all_feature_names = [ - "nested_scopes", - "generators", - "division", - "absolute_import", - "with_statement", - "print_function", - "unicode_literals", - "barry_as_FLUFL", - "generator_stop", - "annotations", -] - -__all__ = ["all_feature_names"] + all_feature_names - -# The CO_xxx symbols are defined here under the same names defined in -# code.h and used by compile.h, so that an editor search will find them here. -# However, they're not exported in __all__, because they don't really belong to -# this module. -CO_NESTED = 0x0010 # nested_scopes -CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000) -CO_FUTURE_DIVISION = 0x2000 # division -CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default -CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement -CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function -CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals -CO_FUTURE_BARRY_AS_BDFL = 0x40000 -CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators -CO_FUTURE_ANNOTATIONS = 0x100000 # annotations become strings at runtime - -class _Feature: - def __init__(self, optionalRelease, mandatoryRelease, compiler_flag): - self.optional = optionalRelease - self.mandatory = mandatoryRelease - self.compiler_flag = compiler_flag - - def getOptionalRelease(self): - """Return first release in which this feature was recognized. - - This is a 5-tuple, of the same form as sys.version_info. - """ - - return self.optional - - def getMandatoryRelease(self): - """Return release in which this feature will become mandatory. - - This is a 5-tuple, of the same form as sys.version_info, or, if - the feature was dropped, is None. - """ - - return self.mandatory - - def __repr__(self): - return "_Feature" + repr((self.optional, - self.mandatory, - self.compiler_flag)) - -nested_scopes = _Feature((2, 1, 0, "beta", 1), - (2, 2, 0, "alpha", 0), - CO_NESTED) - -generators = _Feature((2, 2, 0, "alpha", 1), - (2, 3, 0, "final", 0), - CO_GENERATOR_ALLOWED) - -division = _Feature((2, 2, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_DIVISION) - -absolute_import = _Feature((2, 5, 0, "alpha", 1), - (3, 0, 0, "alpha", 0), - CO_FUTURE_ABSOLUTE_IMPORT) - -with_statement = _Feature((2, 5, 0, "alpha", 1), - (2, 6, 0, "alpha", 0), - CO_FUTURE_WITH_STATEMENT) - -print_function = _Feature((2, 6, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_PRINT_FUNCTION) - -unicode_literals = _Feature((2, 6, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_UNICODE_LITERALS) - -barry_as_FLUFL = _Feature((3, 1, 0, "alpha", 2), - (3, 9, 0, "alpha", 0), - CO_FUTURE_BARRY_AS_BDFL) - -generator_stop = _Feature((3, 5, 0, "beta", 1), - (3, 7, 0, "alpha", 0), - CO_FUTURE_GENERATOR_STOP) - -annotations = _Feature((3, 7, 0, "beta", 1), - (4, 0, 0, "alpha", 0), - CO_FUTURE_ANNOTATIONS) diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/__future__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/__future__.cpython-37.pyc deleted file mode 100644 index da650e485118987cf7cf991ad3677ecf2ac22f2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4175 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/abc.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/abc.cpython-37.pyc deleted file mode 100644 index a6d850000004be26c8f0196b0b1285ad1c38c3db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6494 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/bisect.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/bisect.cpython-37.pyc deleted file mode 100644 index 45647bda6f15a76150dbeb5ddb970195b1a788d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2741 zcmds(&yU+g6vt<5$D4Js+eK`lV8v%jC`RU-h zzt#!)4I9g&36(G4GF>PH=@QWvuJC@OT`D$2L-;*;)VxJoP|->n zcgS6mZF@xe<3Qh}1kd{L^h<-^lPnnSwzNtCZAxJ*1@T#pP(a<(hvkWUlKJ_xG;#p=|Q$ZVH~A?xQ;7%D`s z24WI5keGpE&c0+uay^Kp=u~b^VQmk0Aapu~#Nf~J?EOrRxK%T`f9!z!82f~78GOT& zsr*vwT$e6nEB$&tVWXtHr1R2A^3sV_>848jN^~0@`}2Mj=c$Yq`6yCK*5QH9r0%GI|j8`Cu$F5zS;aixSn3CJP(q*+-pEqkctCXR;{UkRCRo zS1qCo$;>tsWW7o2GoWqSCO(vU6YNj1h23w!W$r=oTG&F^ef~YH-7RUSI;*x=WkSx` zqgZN*+p*%|8Q5M-)*ZyAjyS{pV5)*|I*1_y2UL@Uff0Cna7BH~Vm_15zWN!P*9dLCmHQ^bB^dL*o)TTuB_(&zHhIvHR}n z?rR@5>OUaR0`^ggaDMNu2sooe0qBz6I!gf3_p(a#&jg$^CHfaa1Y-5dl&CLqLln5vK`3l1`LR4Y+26#hS(sw}f@bkX^!uxu;*6WFU(CbxSQH>H-QLHfr zIP08cYcHL^D^UL)__eW%e+XcFLNP1ttYou!HO<8|k=HPPC7GTRyct{!wu4I!e6%;I H?|SrasprN6 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/codecs.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/codecs.cpython-37.pyc deleted file mode 100644 index 1c346844f87be35560d0c506df022f41c74cf9e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34159 zcmeHwYit}xp5OFL&u};*DT~OkC4mq5m zyJtjkGP+A7C)wx%EuKHKizy9y4J~cX8%HS{i?f1Sm^zBUM&v_C3 z9mdHC{DR-kW-@N3oN+BT+px-(9JA%@`UuW)jog*Y)l75R&Up56$)B|{<-C>Yj(Y{y z_VT+kx2&7i)r^~Uv*r9(@^5F}$uzTXXWYD7aEIKYJM5O+ZSIIW>W;bF-Ent^JK^qh zce(euyWKtRUU#2+zx#mup!<;fu=|MXxR1K~-2?7H_c8Zz_mDg3PPtFGPr8TQBkr_2 z;~rf&Tpn_tDi__S?M!*NTymemaa(!BeYQO6K35*|vP;|D=a;kofA&gvGG5-{jg}{x zBi@L<8Y@qDrSeX1q`V7H?(@dVyT6!mUvT%lpKzCd8aeco$e+buKa9_doE8atR{xGgzbsxm_gWf(| zKZ5HM?gO}fK&~BJpL8F>^+TxbQCyvJAI8z;Fm-nYsJ+^@P{bc;AU=)UGY z@_wfLn0wxJaD3eTlKUu*hukl_`*ECfFSrMAoN`}x590WQ`!#pgJ%l%(bSv%~?j+6* zyBFPG!m}gpCHFFp)9cTAGwzvNR{1E7S8#j^$2W0&8ppSAdI5OYcI6kK_;`!y$ zce4K1tqlKx0Y~wB3csiEdj`K}@q12VgjIgQdjYxIf?vnV$GjKacb2ob^PzVT<96IF zyI;AL^RkuWa{ZF~6}K$cFS*&vnW?XLKXhs>*Q*82kt5E<_4Z<`>73>b=aRQj58D3v zVdvz<^G>ztI*VRo)$@btQmJ&+ueaM?)0ta$Ua$JKBPW}#?>QH|mAQ_;;7qPm8z&m- zV!GB^nZhfRwJ8+5y6)E(7TeD0*-Ph9aHHW|;&p)90?)tZxzo<<8_v~}moA;0z48uT z`ypr6?35K+PjnwUSFJZZ*J-z$MyrbBqUX$Y>Wy~2sT*g@n0NZ@eBBkW@~cRmTfw!y>Mqd75|hnZEb@v(Y`A>3fwoubev; z4zmQDJ@tGzVosSQafRZdY|lJx9-y8?HdX7e^!)ked@Ib$X*hAdS@XRWui36P6!?DX z-WiWg^23qKZQrY|T=J@kD-IH#O(dV`d!x}k^?GT+!)V6m7=J1DKHRUz5JXw}Zb!L? zksDAD0-mm^>I>?vu%NPqB?6`I$+^Bi3S_I-+7-|DTYeCZ))$&B--|BCd~dZ;t(oh+ z*H;>~#j5Xn^LswW^7>=0r&pL@BbhG zEzkVyr*in|&jMSnK;wCm$^7(Zz%$H-hF6noo#b&mfnPwD;AOx8GUcpmm2;TAHYj+` zwZChTqQ9Rj=SkH;GYW1FbF$>$hgZ5sPs=oPy*98uaMl(v-3VR1x!`nG1^GEhHAgkU zU%$d>vZGQDDsAsN`jO*_%(Ws)v+yI=8p7{1e!)c~?aW73FVnMn*vd zz2Qn0_l7Gu+#jyky*$!&>A-dd#++S2U@P@jJgNjNb8p_2C^Y#ISR0Hrk+=_`d^{tOC2Rk>Ot@J-47^Q_}J zCeJW=mdVphm_4)uuQC6-8UICG{N$aP#ny^9v))>msn_f6%Hm8l2!L^%X~B$(i>a`Ei*Gl5^5A!d0^cjlVcyf)LQ&&{j~!F*==g&7%&U>fx8DU|;;{DR#`GPzw= zA@yIxRdKtc?0TQwBN;gN3hU*#DGD3P#MnGu(95{w`zT6WRSvf8oH8m`S>4reFu3y5f` zIalO-1DEE^ITkAb=~O%p5xZ%=SczEj*vR@{vvp6gR?uR zErR3+WUfHMYjw_Ifl84^r|K_sh^W&Jsti0+00}5^UaK}bc)JRQyy|C5tzk zbx!U`Olma;zAvNA-lw2+=+#3G(}s9YI9aw zz{3DdICHw$OqQ~N`LUc!$)02js;fXB6v*=4e*HoWMWXK#r>2+D_ky6n{>fIev7VwR zkmbxfhx%FVA*UY>lLK;_YO)h}?{&~M9_CJ5Qi3<55c%tC(Yv#MZF+k8#)eYjLQH9? zlYvbzFJT4&pf>QusWuv|HGrw-Ppt~^)^mWkAo;vquWD8sNeg=JhXpmCY9v4W-+JZd3*Y5aD%wIe16 z>@>XQ0%jQITL6mSQqE4cUDFFi0#tQ!%Q2(|qBO9iu|DmbZ#&3W?KFUJ?N+K7LocG& z`l?|cDk3K|uGwlkK^w9gQlcKDb7G^g2VCGL27lUlGeNls^krf9NTvbI>S zEdt_enAk06+4EN8a$7!x&3>KQE&Vv25CT%mbl(tY$%Fz{IzgLbErbV^NIN~J z>-o?$R2Q4^N%f2xD-4_Ct*o}!BMuB?VvE(lMK{~)tGX}hL8_3T-tJV}^%iEhxld7U z=WMHeeg(1=X`tr{b)L!zQx5Y2PgqbR+|Ml!0O!6*3yD z7Vz1lsp?xZ2+gR+)W|CqsQL2Td_^l6bDeq9TSOmRgJ?NHqXoXGIf7z{!Qtqknl_kP zpwTPdO3PnQ6|sV;fQdd2{ZO$_?|PN}56Nm?!xW@Aay?M>#p6au{tC`Ir8j>1S!cN5 zRo zn^G3&=_+&$OsLhm2T_93tek+rk~%8lYvf~9#KzjCESf-8<{)>=n~JSyB5Mde=mca6 zNX@W3c+iz=;OAszrXnS7$k5b;FrwW&^2bpR#*skt%~V9^s=#uK{>gR!(h!N$P(RzG z4FkK$u(p^SkjZRp(q@`K%$8#fz|=iZ6Ik}v*T4f48o^~x$-hdubD&@;B52B?c35>9 zFnW-xt+t@{QruQTPb`szFuG+0_rroBt+*6@aKL<^dRK2kjjnv3{Rm|WN*dJM2R61H z`mV}(?r!){_oRXQtd^M!BZe@h1SKMq?*&9i$lr>_#|`0ZD1y!jfCa2gwC_9` z>b3v10W#O!I{-+@^s!)MPYO^q=qFUUHqJ56k74xL=B?l?f=f#ge{4Xt2ckoiFEt|v z^=QNN=w*oO?9MGg)eR7#LS)A|&;(P2LLHDM5Tyu$$%JMztJdGh80Cxk!nvv8fjr?g_A0T^{}PigGkKj!%zk1PL9+dO_$iY}9xP&8sZh)p3pLy{ ze>t3;z%L*#OEHQahEdQU0tXbFNMsZi%#a%xg}WU&hTU-x#GT>&r$pBB+>NN${X^;F zD~lA3wDEv+W@Ap!XVI^qu!DZ72{Km=Jh3;3B%=99J+?m^fxWH-Y&99R{H`U{+NDN=t|zn?G<`pJo@5DMvQb+gbQ#$Sbn0vcmc2@DxOb!{W<8evvmeCz_J! z&yYvaOKT+CJ+OJl8oF5%>WbHRG!w;WnFI!ASWWY6MY1{eN{%_tvlyF5_QJ7>>KSD* z_WmpGDGHeDPHhEH>aCcZ(~s znZKFchkTVx&sOl~eDaWb2Jg#4n1XR;-0 zS9Z+mKDtG_22glTB5BSpoG1*qZEZFFGJR$I2O3djdjBP%lEJh}R@d1AqAkdI35BqK zSBr}A%nD`3@NZE$$;$s>D@l;F*JePYq?vMy1Cq~YZsEah1@O0P~h5B?v5%_V#5}4w;-{W zyNN>G9~(xkBvzFHSN&XJRi2o7>a?gCV*+Snn#)*93pktcjlrmEe=RS6Y>8DUCSNs*(`gL92S> zF2NW?C%4e51Y7QwSYAPQ%n*(ZT9xhd*Mn&Ve&E1J1-0k0wq80HW-tmt|)9K^5P_}2KLQiink&$bf;7M4QGC$*cDuj!4RhVu=7k zG61G}hftzar#Xi{lZYC^Hz2AemUo!J`9x7PY4D|-4M`vCHO~)y@?e_*s0u1Vi9Cv) zF}Slu98C)NbOdhPH}F46WDO>h;!!H}!G8-gRc`b%B^q7dCCL$nzZ?Fi`;yZrX7QZ# z{9``;PU9EsM*{n#5P>D@b{5vjEG?Ex*^dwitIU03oOs2N7!_r)Rx|ogK-EX-7Rr1m zLFx=RomS)^*(_U`_{n#rF=1X}T&I+=HY}(z6$c)~e6Qlgj%lYofzZoTJEgRg!7h(C zq><#bY@}2aBN~%D9)mDzIrs5O> zopX&&07@spAHw_92uhTZ4iE_#K8OGixJccjfez;!-r)61a)pMu3!r-2YR z1Y$vD7X6r=L?bmr0dbz{smM2hcoOlaLm8?%wT1_uh}3vk6(N%fAR{iN$tcit8S@Sz ztR2L^2aBpAhFhX!YUTo;Xjt^K5R|pWRwE6B8bPIq)mqTpH?&skW1AbXZ<*mK^b^~2RmAd`HI69k6h5)U6sTbR3X>RfOsRlwj9Z*7R`*rd z3l=@FZ_+)dh5m&XO2_%m`>hq}@ebk!{l>aNBMJpE6@V;BIu<#l8KoW$K`gAc+kPMD z;kF86p7^9v`3=+G`R?8n_=!xL&xf9J4@nIG;TWpzuMIKc(9RL!Souv;m(|_fSC`I` z(w2-YB?2sZ>m$nyA6!ydP3&roR^Ua%&Sq3xn3w2-Fx#H%hX#QK-gO2Re3$^HpRB7K zv9_tyf&8y95p9BK;a8Y^ok^9+Jd;@Ai9N0qA#Z63?=DAv;3`l$B14q=%dLvt*I<{aSCJ`rcJ zyidg0gIwZ=JKMO-4|hhm)DOo|Zw$gOmi*z_b}swFy>Tx6!*PdO0=hot?*kZH2*1;K zoECoR*aV}<-KJL#%MF(BtK?mZ#s$SNsvlsyH;BeMknGco#+WW7czu-jiV=-?VDxD#z+w}jGa?~|C7Pg=AtfB6B(Bbd z=k6fIQth)QoMdHxOw135)zLM`|ySw$m(Dr}7yJ%|T?$jV87;m+NuNVTp~*Ybt8NIzsObIKgBgjOSxNM-OIST2=XDh-ooAdM}^y&8+LO< zom0-d!Q4YV8$kg1UOs?qyS^LbrHHjSSycBWmzis-+vGB=7?5q+wc z^Z!KU1T@8^Z7NV8ey3Mh8et&I2iA>Yz%+adYwDIQ|3BWuis_qJV~usO){WvX7o#=Q zsBy@(bhyD#5Ay#~u2*;gh5)R0vx6rtX5M?^Dn${r`8$^X1mMfvC?S;|X+F$rK$2w% zav#cpDKFO}xh+(G1S!WvPm2g>WP(6h2NJ4*7D!DjTS~@*6xA2kmU>Kl4d6C$>lD|O zK-=svQj#i}8hbajmIR`$_Vc7;{FVD+8ai~F3h@! z{d5nf0GgvT+jdrDk*|J}3#Se{%7TnCAT!fxGg8-`lmDEZ;(X@&@ZTvq*pO0_ZSroDG6F5ih>-uf=Ej&1_9tA6RYq|SyhzIn`)?_ z9|DLK1_8iEl%WzWpM zbRlY}6seM~M}O$H$)IrUeXA8~Gs-@G1#4D{)SFRd@I$h-sZoC!2fxnb9VSai!W{g6 zT8(2@`3rnPHl~>N#72yh5KO-vmV#9*wI*r>Q`2l*KQXR5~xA;fSbZ`)98hwR0Gi7-P-9 zj~MesFdZ;5FdW*WaQ1~v8|-K)17??nrhF`V4yFy0IZ`mN;6g74Rs|j71F%4O7mLdg zt@V~$5O!?e$bHAU-o(54p3Md5A7sg#{qMC4y?lGcx zM)Dc@K9*2sF7t8*OV1gS&vs>-fif#PX~Y9X*0hkoS+99$KULF6EM}iRa;B&Q z*sTx?FkbK!wGIPRh!4$b0aC>Nf{BoEY*;M3tMG*;@N@PYEC*ct{X;6$nDqWN9Dibs z{+LsK6ncIeN58|Qfuw%o5#*(CiYY7Ppv6a|1b)Cor~@Y&wuXQK5%w?GZ^9fpAuN)V zkX(j&nXf`b5Iil03#o>H(1_Ud%Gmd#>au~#bb1|6$|HPolqH~~@^*6tD;aJiw0wz# zl@gd|C%_H3h(EIp6BmN~SZ)N<*p}&y75tdgW0r02vUXV$BmsCfmgCC)vFrrWVh&^i zd9!$P7bgD%%79XUx3bxBf#9vl)!i zv_(}fqu&)i(H6x5z-l6~N*fTdC_GDZ zjBuD(D1-1dA`yo$GXhOeThRK3I!M{-I7wuz8Rek0FQs{a$b#5m?+}c5uKVX0ZU~~E z*no|NrP@Z_Y-u|_2n{4pkv=$mq)m}HgxMw5JNXFc_a-U{vE@)}^*l5JS?i3uLd5?D9`!XqHVfenHkF%f z1DpCVefXQT`t$VCWwpA5|I17k znNY4#`iL-qo4kCV38$Y-FaK}x>~Ax&C!u63gfQIj$dE` zN`})Kue0XEULagWj9+?72g3}of_0ffz#QCYO53K0ATD5-4ne@d);%yfVCRxfvqp_LwpBzX1up$#PVxUvt8Kp^_(m^KP=FU40#gUU zt;lG=jasKEd^pr;E;n0iP32#q_QpRR4TYG*h4HUgJ^L1!IafkO=UHs5B?eb?Znk=f z{n{UNG_Z&JxQx~tOmwCmoMiA(-y5pb!^-y`Z-lX-`)EFpm3dy=lVnfnRmqoSe4{ee zmB9(nSlLhsR-AtGQ)E@r`yXLsT@I)g3Ih5TXn(Ez*#CVq+6vC3MZ$<%;6eMRs zXvj&qW{l!CJjH^pVsx0wD|VzZsF%Znf_;d(*G5QM` zN`++@{16VJ#SSIZlWYDR6f7cW#4APN>7$FJP`_{JVm6AAP%Y39u)VV%yJnKTt!n1; zA0%oX)OOZP+2CVWPI4PnehcUQ?10bzC{g)?13Escd=nYFgd*CM_N-f?M}0E!20=_=jEq9M7+8-18a z&-%YLm1m>ygcK&qjQcpqAT`rnAJtqQP&1$ZyF|?o4QRI1ENWRwSY+c*;}=llQj$Mo z7H9-YM=#{mbo>&s`2=c{q2}}dKu~O)Ffe*xH-H3gsfIj{cl*^400eKmiIRC*N69>m ze71U$ij&DFv<4w0G30lnKl~}%Afye3juH$O0}0E|J7i{4nfT8PHsrex55R_dDH;Da zQ;`S`ylAQ?RM`=w;s=VZA!gJ-BXP3`O#i%;S%?QoEjAi^oxxKAvOh2c*V zT|<%byKKS3I4KU>6p<%NHvh4!K@RJ2aV!mu6gP{t`4-;WAS7c0ZN%3^kv5T_JY)pr zq7jsbCE|vG<0|528#mP!0a*#kqgqfNGlKGVZ`=sVJ9Na&1R{L6h4fA>C_f0Gs;AH_ zBPdhgq&qBOctV!K*cWMWS-rJtzFDT!9$F@9t-6UqE3jd6 zpe@I+uPH&-$gd*s27@JDW7MO>TgPh3YOtKB^bDgJNl9Tm)yCugW(C^)7g+{i5F+@d zb{dF$Y*i}@xiqD7|f(n&%_N&+TE9rbH@_)s}^Z~IU(oUNsp%FwK9r@Ih z#Ok>QqN_@25$QJ3*7M2?`V{~N$1rDY7^jDI{D-u)~tjFzGF3;IWF+$)I20q=}Cx5cZH z*8#FL&kxWz(x|F;;xjlxLveepbp)chX(#1ywF)#qZyi@i3_BnitA^AOZBGv~EJota zb|%r-R2ecAuE8C^y@}8n;wXc9#)6{wVnit{!p9x;EFY<{OqG*vo0~5e z{as3Cg@Y<9!CzuVzbp7}qT(&!_rJ~OefkF9nIhOFoMe68kZf_@UO z#!wIH=Or5BIaO0RIX2$3kLLi(pBW&LdnWOGzj?j@$~7q&r1YcFKY4S21AA@p4<3?a^Z8l~3uKS1%SjR$yk7D?oI5an-BqbLU+GmXkgqxweU zURdl!&3%>ifNRlMzo8Cg&o}s*>NiT4=q=%tdYzBVFzQzfRm3eoF9M0*DQS z;m-Q+F8>4?oNx=uVrq{+#=r#*PKw*16I*t!^gyXl8phTW zL(qz`-=Ap3Sb-8+zGw$NqjYL{B>bZhhm2hY)5i(pmGRwoAcEd+D5sX`R67^HxpvD_{D#t>-J5WWk7Zz)*v-^+hA zL^IXR=$lo-IIFJ!jhr{Q?inhXmP4Q^LVAy5M^tblJw75fDo2eGEva}i>=YZZBYF|a zMN$Nfg>j=c&j@LTPMMIH8TW8pLVf$ol0Z_4O0Cvv3?`-arI%|fE!6-Lxge7MBgQvR zb5C>qt$;{ZV2trfi<^t9&lH(LIQeSWHunwL+g$~R2J|>lQdjCQBYUaS2xy%EALu}Q z#ayf=MRma|vgS1!iDteTuRBY2wTj!RHlVK|928@LzNFg?0lM&%vESn$k1J@t-VR<3 zlMD;g-b4POL=0?8%8|~J!9;PQ7puZdYXu5%0Iqtq`aA-B@G0hN|oK_97AW6rQT13L;FJi2SSmM!&0*P^tXu|u^$E-LwPJ$lF4je@M z`?8vmu*x7s`56D6*wx;YNW@mN%EY4~f-52c?2$A4%CRFMV9&Zcv@duS6UeR)O!sXT0kCA68TY;zZ_axU=K`h_Fb zv_Q5(a-4anXcZ;+7a=KGM)*x2xR*h`Max7$&@RKD5Z!Y)(d2Z5i)bLV!{v0t#*sud z&sg4`jXg1KEJewKxaNhp77#lN%MFNY7AfLb#Wx%R4(RU^hO?0*V$p|;wHh`v)Psx_ z(ar2HVtX!3Kd0QiJEFU8vN5_Ii60ZWCe-PG!xz=V8QZZ z+CKn9(@X=8j=`nPhh&aZh&zRTC9pm^;TkHpI1X`I)PJ*>u91V-_++j#JFX$ zCQA7$L^e6bcSp%!gzP6}F&&vsb*PNXbPAiaSrgy9!57>Vn#29VWnksfI>{VkRX9X*z z3>Y1crWP6z5Uav}--O;I(Df2OPenVk zszt?#K*$gl%qe8bM#pnDpzr5fASJpCc#VZa901%f-3ayX(|jMoqd#Cjh<;T39NVqP z=V#jPgPXUTc94HLpxx{SGv3S;jW>);2n2;ra6hyGV8BgWlO=Wk_dURY^YJF%XJw;* z9d5+9qkcQ|y}%DMF}38S2tN$_UeG+$)~W@iJg}Ks^a0KYQ#AlIAqaLogI)@^B~TP- zM^p=kG-~$?6j%_E`D6Aym9xw+7Z^Zzpvuj^pZf@$QC43S@b!x|0(#E$j{sd?{y#=y zdR}Mj?|BD#{?n#CpR#9dpmo1@5AZxPzKAbSZFT<{VR#<}BnR1q0zQgIKN>&@KCj-; zo}tgPH~5jzO?qQL9{sOGZ{Sq^D9&@XbNxYZ0f`dhd)avea()Zq{B@_7Ig|P7Uf51- ztj@{9dW*$x{_bAkE!ace+l|FvxKC#SzO%|Fuc;^U%~!ko10hL5{HPbvgw1ucdKeW^ zRNA8nuSY)ZV8Vd zq~}uhc)}-Wvp%Vt$S(ZuX9QKOd4&a4r~glw?+g;`-6Lj@{>l0np0Uqmzm?4JI0BKl z(6R&}#kNc={^v6=LK6oJjG~pFd|=f3(J+6)fzgF*GB9)y$iO%_5x)jx$M5poXv6+* z@$xsBa6tSIne+)tkK^9NrlS!tuN2W3!z)Di_aQQ#fyh7~TK5}RfxHa4)P;eo-d?X@ ziGO?2Z!SzZM_$3VQETm3`!aeiZ$ogVoeJAKLG{AdSmjf_QB()sNAQcGU(dd0Uruxe0zR|TM?iu1}eyNPVPkm)|Yv9;4LH(JpBf>);FSERHlg!ZE)eIms%UY#PP;C(FZq%-B{OUo z09=X!q-3W?woGI}1Bu&_kLrpEWrLOE4aRAyj|6JOluaV^{s>gjYpcgzcn+V1)>@`C zJ`qD7H9WCRBvAF;&e5Y!RdshFG!LJ9Yope5_?E;!PW{k zk*`#`L+m01x^(jr<^n(JucMCH*e}7&bWhg8Ud_3kK@&__%e*4`1bcJ?4^Kw*oH+D-_!v9N$0w)cBL*=f{5~(;d4y p)-KJI9xs;gKZbuC5!Ja1$33*2M*panzAgP~5B%vmeQL8AVydf;YkHahJzE z)9&_EmuKx&kA#>N?1`@v2ZT09u80E%#2*j|4sdHhE?fu_XQT)uey^(Ap4o(m3%0tt zx;|dL_v-y#y;nDumt6xt^GEyN`Pn7I_$z&szZF!zgeR4zVFX6k2v}f7tjpBf?3#F6 zku|crHZ#6r1a?rlX9N{qIkLJ{UhURqEsUr}&Zyq4Gvk&KpR*0_?z!R}X3#${yY+7y zvH2~`3TlC~V|AB;dQiJ(bQ_^z8{Oq@GjM|?e4mi}FrvjDN6B`d;O4G3Sb5cWx6yr)pW;pa|#97b)H4E)e z2IgK}{H^Tgmv|S5)l^YFAb5Dr!%u+Eb|2Y2J^SxWenIt-fj8Zr%p99b;ey z%Yk!`b)QyJtU-!qa0*hic^kBq9H5};#PPfizKiv-EGIV&S&%0*7mmh>kZRtdaq4|hwX74lwOP9yeAyfMd))KA za$)NCl7Tmy)0%{;*)e&EN_8zjQ*Cy;ys#U5VNYV)v2?5)YfLj|hjQ^~>RI7!oRJK}9xf(uZ%hJG*gN4(_d8oDqo zl$Z&w_4Gu9J7Mfcr4VET#MeUg|1(n^D6KycX?Vb+SqH4mIe~B?PZ#UM3W&K^J~1^ZNcIB~;8+T7^m(%u6t6Pca0x#F_S|WD3mBQA%c@k5^pr=4?7-T-&t3D_`xWQp(KLz0c_uw zfS@v}i2y0J_31E~L;=<#^AkMqKtC?AQAk4zyY5?971~TcN!y-(kc0t|nu$43|6ZM}qqSv_Xaee>4#^khUKN1f#HFN>(4lxX z;Da#6Y=ta{mOx1&47jHAuydn5!vczM$|Z55b~(msX~77&3pfDKN#PE?AOY1l(H_r} zvoSsusI?D*&ml~Ayul>ylmF~^BMx;19XG~e0D6DV!#?zRr}!8Mz_A08!W)DUH7ET& zE;}&jI7sg39$yH5rmC(V&%87og^>^5X?cL+6UCvBkM1|lwlqAi?=W?oST#8%tNon9}-X7qYFq|p0` zdZX9dpZJmP`K2LhAfbwnZfy*c5#N|4I~!pb%HD7T+Ys)=BvQH&;9~;_pwmHpy!g^a zD*7ASFaaJ18-UlrMig#uj1`_SE_Q1^8d+gB6O!0VTQtM3wJJQOSG>*(e zO9zzFMnL&$5m2&2ONTp|CEk`5Jx5kE1g?Q~WGPy^B`sMiRsdv*N2d5gX52L75@=ZiGpqc< z{2{*E&fVx{5yp^47Lg0iY|j_lA_Zl9p*Mmv+dgL6*rD%&3 z9FBdEXjl3=SqUxF>uu%By&gQ}q|bYN+UtF2L)&CJMO*Lg)k$2&SZ$i4U7m^;$kz~j zy{l=vk=sgSH)UnU|q#lgbd1zDA#?B)iZ^hFd# z)iGUWGsiSp6MxiA$84w;YIjv#muOdG=Y~oKOOG;CQXOq?n{BBT+e}h{-tyzJNtwuWZi|NP>U^jR#o$1D08t`JPEunNiZx$!u7d zLdIc5TIjC;FV(Cnwldgo#()w#ejk{zVUs4lY6WI0z>F-Du)|t`nVR@MS$Hw;r?N)2 z8!+I2Xg&Z<1{~P&R6504PUeW;WR5~k9mt^>wwggbf6N?(oH~$0J=J;7-!liusRKDk z_p(ZX95<`Wr6Uum3n*fpmTV9=Ku?{}qvSSJ()A)V0BvjskgQ0 z^<^>&`(l;)<|q=6(&srU&eQm%9>p*{KSCtcc9oUp_K1&?uHB2nC}%;=X5uj#f02sM zQ1LhwPf#&GJv5w_&~^_``c)Kw69I@dn0hO?G#1cejRH;|hn5NGHCWYbSuWU%Z783hZrDT*Cak>W{}b6x-Ef9FcCs8Wn9C!u*GLguk2{3Z+zk z!YFmX8*n|)2K2DP#4~6;!8kbvaun$h#Se@h01kBjat{!Bl@3a4*0^5?avmPZHY5YM zUp$`sPdnr!GV92Mco*J*Q&1vS;6iTTIJJn%TgLtkh^Z67 zGx0-G8tklPVqcornX|A`2li?+@dA2I><<~2GOX*Uz+s;-tm#^2JYesUSzRpjUKkd+ za&lrvChnvze9XWqp+v^`U*xg&_$;p+_|b$fw5|Yp+{S{iFaH6aQaWC=jjgbAOi-kD z0&sI^kk`=1O=j#evYB0g1R$Wh7`6q~D+h&$g3<+eJK9?cFpwP%dOavt9fFI^R^CIY z`Iy_%q3}O3wFK+S4|7CQ<~p6NDxl)%IS*ZC#(RJyjN} zD=0|^^CcS8OfaB`B4MX3USHSTAo)-rRE|!pW3xVG>%~>{{~J$AyK1;5TV+jCwf0pD z8tK3!E41*WQ*76L7T};iq#)u7LisBv{GO%#9`Iu!D5zu1W>znKAe^~PbH)2;e;Y2! zCKq*ROP19UxSL{_)e-jFWJU2dyq_&?wBARuU>~u--a|dJ6;|CCln&j3-h-^ZTYXT| zGc#AOG4(R{furz!7IT&k5zu7yY$$eOICr=V&XyHt z%izb&mWiMJ4`A09rsvd{*5R?9AG3WEw5kOynK_{Nt?AdZDyTiBR|dr;MR5r=oC%P+ zku`{$O#|~gpnVZX9L-qKGmiCs2h{68dF7l2Q4?gl=pZ|>kScRCi=SFpb&pP(4=rwcP&h6^t0B+Ako>egHzw^#tq z1kRt16>*x1r>UUaMxPHBu5t3pAWD3h+uKPJ(b^-N=TjY*stu}a&m`EZ4@7d86*?n4zkj- z*!LFx4YmK2x2iwAF}nE$8bf^)d@uf#*S2686jak6V`_L#;X$xY-=JigrgOT=8qfR( D_9;*f diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/copyreg.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/copyreg.cpython-37.pyc deleted file mode 100644 index 937795aa857e3119291b540a780573288c577fcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4287 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/enum.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/enum.cpython-37.pyc deleted file mode 100644 index a71aedd4be6cdc523fb63148a4f8d5683aa4c533..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24313 zcmch9TaX;rd0yY-YbsUznPz82Gb(VdE=*{H|gA2~X0$G7c_c z3m-QP!#8}hV>I|{b<8!ZVXfH>+cdUkaK-L8YlTL^G_D(6*D-?PYDK+l8vK{LC4KiV z8eQv)hVS?Vzv!3zvOnQhmP(DXKj~NBF&Y#8lwZSd#h>W^sPVFW|fo%=(Alv!%ol zzlbZv;6PBn<1`NXNBxKJjzcK>uwTNR60X~g!#ID$FXOz7l7~_9h=0s~6eW-Pu3y3L zL;lD7dRyDqw%3E+7=32XT zsnZO@=c7oqZ*E4xoH?BQyz&DT_?O$QXjs0|-CTPuh?+x(N5j%9-AE3c7dy=*Ih6ya zxf%6_#m#PeV>4)BhUAaGHnvOH!eiJ)MvR%eW34|dM^<)Z-?7kMr~k>~?SIY`fi#yydePi}q4?E$Bw!Ssy27 z*Hv#NXhm}JiD%D-s&)2ev$Yy@{j;}%?ya+(_RX{F+tG5b`^@}LpA9fZ^XuEgn%55T z{aoVOPwGsrKV&Y>*sWkU@GC2OOF^rf;q~z0YE}EZ_cyb%X=w_!f^GjOnV? zoA(Q=R@bpW)>6(s0zz7~<+!AeF{I`GGrNbh>0)d)yO?Cpb3p^a{R8>|8?^9&h5ZMA z`lBEHs9|AjP49#Mjbn~sC+OnG;lnbLddF@KE7EnT{wU5v@~vT2%~NL8R1e{Jtm7GV z?A3AUG`f{^_;KGE>u|w0IUKmEJ6+TR#dCDL)c^P%9S?QCAJA=e0PRzx+7HmtAE`q; z;;A}_-JGe8=pS}$&wlIbkK=aMZ`YhL6=^@~H%FD5O!#3O_@-~YV+_pLj13R+3wzUd z(1$|*_-oD8zy+bZOKs4b+akBRo82eZ+pX13^JXWQZ?P`^@t5QI2DWepy9hPM#z7F% z+oq4pbJjwC_M~!K&2G0BxiY6*PI5D+6TLlQ*!frz`Ln} z=Bn50daY)s<3Unvwt_Q!r!>UuKkKcb(VjHb+w6{7dcM=cBjJVlJ*((XoZsxOc6+zG z7bvl&yrgO`*aGo^pVxZ+W{3Q24eeGZRL8T1NfU+o4n5%Ar`bN?K&xyOP4zg=TiCKc z&hkZU;VgE6(ZGN;EQoPCa2f@l!pT-tPW`JD7k{sG!>HM91&~ZCa8P_bcO|~Ha9uh7)UdpW>?6>W!o{wI!X%RU&txTcl2Fj5p?L=@01&k z978kWxbQCcuTjJR6o(TY`#{Ce|J7>>V$h|)bJv2kn}KqB)Enr%kE`J(h9$YqZs>6$ z)u~`J4E*_u^qtjFyI|lt9Tzu*)b#_4J@6{Wjl?+b>B?l7P+7==QUzNOsAkmeb;n+q zydmQ{PH@U0p^KBqxMS>?_aHu(AY465_O|RD;TCgYt}rZwo9lt%1hu=+5FY3<-x5p} zI5P5NHbP7lv`0@tjViu^eB~vK;Ei}l&EwuhY+6V_BNXx9uVpT4b?&X!Cip5S?S z6@7t{Fz=Y^XJaagk~$n=?#Smjw^uDSA6Zlwv318bjqaPc3T2_*iR{>loI93!J+^kl z?zv~}6z>@Wt6PprC~Xd`7*BfTXo6?h8!MGN=0#&*$2Oif{c>zCnp&oGe=C}lR(u!r zPoVzq_?3a#{bkCrmC9;S{UECPD3O%@Ik{fO_221!HJW1m@0;NTUd6Tlh_Y24$L0}Z z(bCUIduw;B_rbBTwK5&etn%26jh%gX=TubJ?ZbY*U-N6!2lvoxZ zCgyl$KaMRPM+Y$X2k|!Ro&~G02I`*f|A$M<&F&IOwF`v~W634GYE22=?kPFXTOtXK zi9lE+-{;wZR7}%_Oz)k>F0HzCDpgH%H);@Eh+)}|52I^MEZmb+MUGjugz2QNx1z8RoX*~=! z{a#Ah!vnCUx@4-r>jqm1b$g)YwKnXd?ve+7(1h;wPidC)5<#fn$F{nQn=s`9E%q=7 z>XV?|;p|>jtDnZL56v?lnr{EewB}Szh3i49y}0c*J7}xF4RH|Z9-ebgss{K=cg9oC zppyPkn6kmzdc-mBX<_582HPy#KLXvC*5U_??Jf#6L*7!4;Ms+_L!zjMl{YD}MHvoD zcpWXrVWo|pYoR~1LtH2&QXe7$6BrGhP8*j$&Q98RNS(!z7(D7x9?|9#(X4)oM^s4a zIqqmvsHdO4J||l)n&zJGm!qUj(y_}q_%IKH)2}E)`GAg3>l6+G#6c_we}Xs z8jcfA#6v0$OKZ}KP@QD4!p&wFgpCP`HqWO|IGHHGh;C$Mv8|y0csFN^aE3|2>);U> zNS-&qg;1P(y9jzKgZlcj>>qm!b(a-vv5)*CTTEaRjdvXTyT%Ue*(C!S3p$Td{4UOq z7z1bPaO_+*-kKQ{P=-B68PnKsuS4eVK;vmBYs%X^Dvy#IUFw~X-;(o)v-`$^df`ndmF2A_*(R}K&A z@je_MiEG#&#g&J6*EF`Ci)$;jorgIBZyf`5PYw>m2Ug@6u>n4e4-96nqHh}?VxDU& zRq(++(ewM_X^fJkE<}%@R@6=#D8^W<;OxAyjW^+VUtB*=gy^7SM8{SuDBsZ-k;a8k z@8#>p)>Xfb_rE-tj2=Z@lXtAa!RS%+V3NEwIE1UkOQbY#3$8VdXq8w0djn7ybq-i zbC1)FUJ=6{6L%1VV-0MGLpuV*r0TKti}pr6>-3yM%bs0=WnZ9r3)QDlm7>&v)?L8Q z&}^yC%kQmS67Iu^^H7R17{7r6qREPe1?}2@>>~yweMUVdFKO%(@Cw7$R7;`uc57po zJSj;RSUcNLulX5fTc6?ki6vkNW;g`kcUaYLf|E9^)SEHYHNMeGy0r#<{5f36P4C2c z8h%^r>ca1_LQOv(*_pIFj7l+EVXJURA@_kU(RGDQB(AFmjkearI7?^LIn>{OEb$Pv z=jiufd(+@WvDUJi*mZL!hZT$%?6u}*CsLR2+|XW!bNv#JDjv)@A6DvZPa9k>;Hvr* zZx!_mht5i`-PJY~nj_Q+d@k?Ad5W|Ig_vAiYp&<~JgPZQz0MMK-N&c%<%+-)0T2#t zcntz82muWX5zP8PO|v;~NprM^Pv0I-XmG^SM$;Eq=sb5~DZb1jQZ||??M+_iDVlWZ zGu&OoZtjSBg~wFW>a*Nk#co*CmbtpZE3b05$jjxhd5h-!?O_?lxJOz8mQAIus}Gf+ zS|p^#R9iErHtmNMDJD&Z&7)yskH&&P#_)P!Ff8}{FtZHE$6}`r9eK}W?mdkez)!s{ zJf2SS=0;VIhOVVi!SLV?Yiy(s@+7eyLB8y!rd+Wk**!!HjF1w^DAmQzoe_Jt>d>OC z*j0N57H`q4(Gs@nID+Nt)CSj+Y-YIaad z6Tm zWO3}og}CTj?-5qAn@3Q^6(DCok5mHx)0f_YKSeKG)8`pF;M!e4#^2xmKn+O%Sx0ivRrarnn#rqmoZ6+ukTt*Q-*~sHU^2jcX=~R0@n0GJrIz4sj znYlTX5(i!ItHsT3i+EJC<34}&m8`DZBkrfgxIguTRPe+Z?a+SuiPx`Oc3*n^%9RE8 zg;&3D<%zkuT*t1n{Q@S?Hy|WD{+@FhQX>i65K(+XqiP@!78W?7x2TUXc)Q2#1`C8Y zQtHA}fu5443lYwFz{9tfp(CFR*8z5(h2C2u7}9C4;i9j*FzT!{A=FI}VsV?1dqa+H z%*kY8VDTVOhMqbLk<0KD-@$gAN#3`RT5>J#v(rxeuN830Yv1rDb4i=7p877;YJ z)mE*|HI0sp%@>8mjWZ17$pB{~*xmxgps^ar#ZbeEbm?i{N0$pQ!?qz&RG+(_;V#Aw zYCx;C6vCP-X+=nMWmphm-s`zN1fqm7yoV_esdbGbko?w|P}C)|K#Pq+1#BYip2Y#d z*a%_G(52Jefz1hc)%F3k`u05=a3k&`rf2m&0o$|yIapk! zG3Ee)o?bU-v`JqM%yF4#)s)2?%`w^wrmSgUUqj#Hok*k~A&!ymK70Dhe3Xk@(`nNg$0e-5j7)7lGtCcj8EVS+Oed6T>R`Fe#U~@X!_^a zF20B(KW1CV?Xkhm6f@1oByKPhK^4<)+^%rI=?%UCS241YEAgE6gLMhteA`MgC74lQ zH9v_r>%gkW+#u(^iRvUJi!Qk_5_H#rQ-ig|snJ6Zx(y@1xfJ-LIC)4Nk2`@9#oz8G zf}JnPq>@PXCm6#Pw~ZX2{Rb3Aux7odpl8VcH$*9?x=`x@S^`;3jM4E`u&Jn0b6pAD zQ&4qqLOO`L@(olkyIw3hKdWo(VU%7&)an*Pd|3$!GRD8vH@G9e4a=VkwuL|wO4KI! zE{+3*B-otieLiD20K0^CD=3AXK$u8Vw$wnUx z2s>ChkI}a@{GV`q_R3K&=t3jg!t;XM`|`eo-2Cxg*Z&7;Mnn@fOlELt`6G7MlNZEn z%TcX1r<1~raKQLRs5VdTQ19JVXVWL=1JWT}Jnt^_5c(G5iB?6%1TZj~F!G!Jlf7C7Kwe;Pyb#W=@)xYXpXg)S)RgKhGm!eHZtavmq*v@kAzIA3RJFA^eLR!%CHq&>3N%CgFs6-aupfcmeL6Z0e zCxl3Un~1v&Bf*A=a4fQPoEvbS7zarNm+=j!|36=Vt-K0HLu`1M;*0?5l&-v)keABO zyJ33`NDVB}H1jKUC$tM8mLwe>S17iX#E5%cTo7+6qwSCb2>M;`p(3=OBc)~?Q~We8jpUO0MVxMNdTCx5 zWyW-1`{iRgS7s1EQunA*CG{DvwS z@2%$m6xRmRab>3xPXp7h#Z$1{B)<$%nwfYCQJWcwE?794j%OAnk6`02Vg%2|7HXIu z?8CeE$$S12q7D{gEO-~Wi?^5Kp;g8iNC-(RZ%X#xw^9zIxz`hPKqQ znpUFyh<=#J04V}=ne}F42k&6q=<9%BX1xRPEcm9>{HvIXOT8`<%-R8xno{@#q^tdA z$ZX;*BU;VLW-+yZ8)%O-2SS{7!CM+RNW1`2bWYiXXW$efJcu*{gaI_zAPH20FVGgu zIKqWL1hfHq#eI{pd7a$=zEA;kHSs(=-H*G%RSCv00>sde1Zf~sf@$+@`2SPmsa%x_ zb}{EB-~|C0{&76^*1GPK7ao9jEa*T8!E$jGb%LU3q=T9vU*fITxD%&u93fU~yzxAC zLy6x~ZsEJNhUR^`AQ^@}f}@ z=_OFH`YLbk;jL?+`m?;toJtK#6UJ@SdaAwDhT2cC=E;0IRiT9(ut*!F;@3MgGSw|S zIIJeZNemVh@sb^EwRSm7YJeNxpqL`QZd8lrL0HU$Zf8sv*0Y0P&0+l3aRt}lz5=iX zlxqRTJ&b#}igZDMzhi)a=891iCe>Ra*VwHXZgFHp<|1HEdVrGMiOf#$vV~xjC1AmP z1iw({Y%$??{ke$od~3x~FXK)@?%-#!Pf}XuEyu|c=szdVN$`TKBG+cAgymkw z!PW~gW4PxA<`&@(9-k&a5>e(KM=-7q!>FU*NHOX}U1!KWfICe=0P#cj2J2n` z=bieJBx6WZ&bagQ^KZFd%G!43Etz7uId`LfG|}|P&O*kJ+)Cd9RWHLr{73yQ?j))t zE{3DyL_54Hp`p+5XqQz>k@Al?6!hARGGZN8xysz3GSavi7s;D)x#7r6Ii_utun9ZR zPGA&(Y#@dlaIw{ifdeIFfdHbdH+>r<@$#U6kUt1vk;?SUpa}Q@rT~mRBx=MZfG8l5 z$j0WZSj!HQDxQi<1N*A6@f1|4)Txf+>^MT~D8+O|{^AYq_|Bl*MSc)W3Pv8vi!>IC z%_(#-&r=CW)B3{%Wk7qzVdSSgm*qG|$c}J?<{mk9dCnk!+P& z?!LX;6UYQagf#sWIF)9NP~D87M_D-M^2ET-Ncx}%3z(8Un5e2PuG)PpEZjwxbRAPB zCof(DF@2k7WMsKCqOG}!Tp%usGb)9WL=Yu@S59r=VG;2n+MXdR+C^|JK0<;!g#)8n zwLx%@#|*t$_;<*M2+K*(&MFotjUBVUf5ekn448n%(Y>;IZF0v(C+{p18W>B z&id83FtAaIRyqC$g|8M;s~o-tFktv4-;a@V6IGz~2s%vaTxVpbA-4>z|04)9{abw7 z>>f?d{u?X;W;0L5PEy{6c(lE0Y$t0wY`wN431>+_6WKK7ZGLE}AK^lFM!Fw(V zwZe2pR%{N9T@cR}iLx|FQG+(K=B9M$Wd-A|jX_Z=%Qzht#RLl_%|S67GMu=w)e6=r z{j^moCgc;m12B`$0F#Qne8fiGVa0z_s?+Z8&Mi<*-;&1siE=Aczqq_M-EqAABXFP%j(axkZbiHLg5NQr} z>HVvM?xP&EJ)1ZjpF|Ck)UmsjoQ2P@m3*OL^=rCqDWzqWA-HtBJsNaFQUD_m#)`dY zrvTjKdC)3DJ%r#K?dgzybgb$v96^M-ypYLMJz|u}m)I7WQH)oADw*g9;Bhk39PE5! zI6RPJKmrTW4j7Y9^JQ5R9`JS#gU|z9eo`9AV{roV2t)UO;@-~1V`VtH)_m( z!;Er5#2>>kGs85#YHLhgru$2{I@VW?6p{c51WVrAtL$wN7mFBcM4|*E09#2EYGfae z9?%2H(3g0Uc(aV`>wJ+VQ`)FCeIGF7&0x8CtBvq8r#Ni{-!BUKv+0Wsq~O$?jGxED zU!;PJ1)jnQ$c&s@MywH0S}u~oK-=9auVc(Wgml3Wb;O`EXN3kuLACi-F{;JCCjF@! z*nu=%{4^$$+%_&%5Iz~&kcqo#lTW3r%uq5gD2qe(R*$C5KdauF(}zS|W& z7&=(kx-49gj?g$mFyV(qkoLnjvo1ifDNpD-V*(?4TMZ>SD%g-*EKaDzD`dKa1NC&N zkD=i1u0DoqLGFe1j0w3|P;wkIc3>a5Ngqi{d@D!3|L`@K+{9ng5CLmR6w*BU%fR*C z-4;RH%Nk(!C!_(a>&JNSBYdwYwFkWTBLvV-p-oZl#T9w6RJPC}%kq!bOBoy4IQ$-V z#0nq-v3d#QSh#B{tdG76gX)_mGO`QbG~YFl;cW?$P`+#K*olNFZqLTW6(kwRI`hJN zrmT5C0p(PHa$48QNlFw)B@&E~VfP}0MCmo2r#K{vtbm9o2q|^Fy&f zq1FGGrcJa9zEQN7%*q-_GUc4TflYt{u4b22%9uG}5nE@@Y0;_$*U(H7sD(4xh++AB zr@401Z(jH%wB*0ziqU`cfvwObLFZRcZmcOBFKG&CNjHUZU1yb~V)O6g-fs5%Oh;Njdc4F@c9{7C}QNMv*qo%7)K}Keea`|Ye8w~R}Eh!ou0xX%CZO+;;+%zgo zz=TIwLb|18VbM~}BC5wlO8_Sl;g&o_0bbwBBh=n3EiCmb+|i2BE*-VFb^>qk=yF5{z#=cT5R122LEPJ?$ddW`< zg|k0W+C^+aW#cX#rr1`LAR3ioUSqb_R^#GWW8HI45d&P?WLi})2LnF}nSdY`%n3Z4 zTe!7X7g+!I*ad7x*&I_5dkSkN5^%N?CBCOt_=mXv%W0*CsdzrtYa16XVhh)?8}GGt zWP^fsW#MWTaV(3yaQy%5%xYH_i@U^)ZA^>XdPI?r`upBUl1P{nvWTx-gqeFl?UcC( zK2BmQ#OhMURJ7O0h2mQ;WG=(Aa2aXOMD`ie_U`Aam4Ycmr)CCRN!iV}o22Tf7sX=o|0NHxo4 zwMtf|F2z;OZKee>zc*Ea3gP_jXnm@n@=2wedg=G#?sVOecptep`VpQd73-KQTu_Yk z*c-GI?H^1RiSQdE`WacRc>qHXVy0(>$i;GdY1zBkj?}N>Tzgu@y*w@TcX7W_&Wexd zUNi$m!QUZu^30gv0!i&~A#EJ7fc{Z7Vt%jXt6s()R4OFmOW0&hO3Ve-BoG5@Pt0k4 zIHnjz$CAqj%{2AUOAH8;H6KX26XWxe#Gg@1xm!2XiTTjT9QAOlSI-T%Cp~Q zcWB5NaE)cHr|kPR-IdHkLoxZI@?{sK`8RPuQw-~>&;dZVbSY>$e}!f%W@OVP;#*%!qGIq}LPJNZxu#&xH;M>{^JO z(G_WmlOq#DT!L^H29r6bkHak7Bj=PK5J|F43m4^RmHrHp4=KO%Ij3yEpE2k3#krzJ zdY(qz>g(M7CGOtlPON2Hxi}sch#4i4O2lxM&LnQ>8#9x?D>L9U34^l4mG&6)q zuawI&G;iX7G)6XC!LUFspCHaA_yVsb7()b8l4nB0pkiId=Qk0=mX0lY;P-M*VBq?B zRN_N3&YFNm3)_e-Mx8Hq>+HbfEUlR9P!TKm*g?)_g$5T-k{*m6pCprw4)<;vqRIN7 zIWT+=7TbL+84QhR>}9ZGHe@2CdQth}vi?(69$=UFt(vZX8yAKXShB#_K;Z9w`&V%L zPx$s392hXNDhQ3vz;I^hv_Cc0mTW}ECgtmRZr7x^qe;4flsY7|#Vu8Fu|h?UoTh#YMaq|>MC7Cf$;VmY$1Me~4wJ4*cvv@dJ< zpTk`KkKA0k$@mFEwC7Zoc2A|uqRi(JG<@&*R6pdcT?|IM_P_AmqTpmEXE2jT%~^p< z`_+6~vH_vA;GhV9?Fm6}$&e;uQ_zJVRbW%vlSuQG5|D3z=5g8Ww@d(fRQ#Ot= z#DLU+w3$pA$a_Co^DgeyJoS5Qf=I&zI@zmD$oGWh?s>L7-l%kTAseBy=m`X4(Hsoc2!D$ppZXeB{t<$`Rps!0?0&$m;IuRqt%hDH( z@C1XlFTg`H=8GolrwsYGH0>Pd93pD@o0-gNl@(ip-~@jsKEIzt7#j;_eT)8_}g4 zkwL{7`P-z-!#IN$w95Mt8JsOw%9G_O_>cwuw{S1}^SPFe?9-@eXye5> z^Nr&TV#rLjMunjrZ6D^wSB93h@exio9X-!92mdos~AK(P-)`l^Y zQw3{>Vf_8rTmnJo%wv3#W9!wppl(6GA)#kbM4yZMnetd-4IuR|iE{6uyF=JTxkKJ#EmmdHjD~MJPK%kRNO&5M5sBJ4}OaC-MVaL!!L!{azG1BokdX-22CY^r zzs5o%9u^uSn_tLi40_g~6IshzFPbM~6!7`TiampqRQY{$Ye#xUGsT`QeXz0-F?5-Y zzoJ7ESVLqH|7;{tc`{w z>Xg^Td(9zb^Xq&yWtagNpkE&i&PX5B_S6Tzf=4u}NHSOBVxP-85S7Q55fGqJGR|@& zy?L-sp!7Y+2F>DtI-y#s9xE5A37940SeXhQGux=sI1u+>DIX@JWc4qqWTiD0xdvOr z=ZT91gbUkP?Fm5U$&Yi{rVfKZ2=@ckh zO>qbrj&QzjopG}+pli~FUGAT@b0C%>hNdl3f-IfUxYaIE z^6MP1bO7N19@TBy%U$S?J}0NAj!WB;?}giKMv^GyV0DBiQ?X_S z!XM#e1eg&LQ>T4NVbb>Fj&%>yDzR~=dl+U6lAG?o0|F`_)0AI?I)gbVQrW6knQ4C! zIrmVjP{<&lqR!@zOVh?{2>oun3L+|m-_be(xv1ZfQnXqT;n8Xtkv3q?{3^3weh*)m zf+~hm$CnQs^{=^x0ZyvU8^YO6Nq?gX${Vu}maE`1D#VFeSPOy$R0(jEra&d}#(B}r zW0b|w5z0D_0|6F}CKj}{VhF;4?;Xa74yN>#A@NBd|2m%A%kotutB|wASI8GAkBxw_ zy@+e?cG0Ypc9BuVc+>3)kLeYp2;1#ypCxpM&%~|wZetlM|P)7Y0cjBCjIHXjY!$(zV2Wc#K5=cF;EL0TujdChc8#R^)#ggJDAC=XvF{` z;OHu27&x}cS$E9+FhntwSgOtrzo=K3nAnyMS%KbdsrELo0cZ%2Mj_J^1fvMJ^ zUeJeP{O-;uP#o${@l3*tN5oOq#v*kyizD+3s~*2P?CI|*K7{Axn~mym9<6dmdXx_> z4jrc8Dq1QMlG7P%R5t1lxhrwU7?ikL;@L>Q6vdaeiP`SlxXTRCsz3x+M=>vu?qqEN xK52(6G{y|-4%4&{?bClH#1Bd{pKWF4QM;|`=XzQ8MZ*ZFzw;XTLgr&e<@ z{4=wxPvbt3LGB1wWlsI`!(YSruA)BqZvKKk{;m3zN=cr$o% zZ*}$IXDiKeq)Qi6F_MFbSe8eI`;JXK8DyB?^^zo2D>%9*$I?!#>mz zD2P*|c9?3|unL{sVH%Mx6=VY;LoI@>QJ`g*swC8AZh$6sV>B!Y11YwLNhs@Le;|cY zWJwS}*$8t)fRn9JwmX0;_!Jzx2CJZ($v_Q+;BOc)n^-hv-jG5M;j-7$p3zi?gJ8iR zOQ&v{41+z5M>^mc)}3a0YE2O9R6n!X(zXGc1WaP;om@tRiSk7yeHro8BBM4w$D?W>-7N7 zlL<$HP>SGpX}mw-j?$wSKbQCBE6KqQ_lwpKr z8{nD}dmCr;5O9Vdu0UP_ua?N^gj1k#?gVFm_fiatbqt<@PI1Ob%WTDQxf|H}2#A&$ zaX&+N%n)J9r-5J`(2XTrM?12dW^y-7;<4anT--H0D_KiKRU@UvF8H=Lj6n+8YXf}L z4My1zTu6U}O$bwsak07?3=s}zcKj{zQ;u)Cg`KIwMG*7~pR6ErB&C_AUAPqNg#+PV zEIEh1(@wjW?TYp&+iu5ktT%h@5HYfy?jmSao8zNBklBuiwE6h)PuogH?X58CiG)MQ64Jm{5+dyCl(P5mQ;7ceFgUv6+IdV9--Sj zWax~xxACE^+|r<@Y-o^|qh%<|4%vaNS&saO9w+sQ#^`gjdsNAtW47ag(Dur>{^;p% zmp}gaCqG~QuvsnYF{q_Uyw3kxe_ zbsC?vScm$w+xO*z{a@wQ18ZaHz|Ec9J!GyK zGswqZShh6+E!Vm%BPB!Rn!KV ziuVosyl^l8Nt%_SLbOxHlZ6Mr4HGTjp&>P@h=;G8C@FE>LQzYoEZYTZd{&45e71;s zku9*9^N1;gH_p3+2H0Ylk%KFTI79n2V!`;U|0}26MEFO^&}3(d8svM*O{)mN0RJ#R z;-d3|oHL<$qlruzM?I6gDP;dQ_{-SW7%R7jCZx(JU1^pqXgZ|}h-0Nk-f+h3dO!`! z^Vuv=$aOQ`e24Jij6&s*+13F_mcL?w5sW*RfyrI&_HB7T zcX$Qg&fXGwJoK!hr#kEL`!+^@o3n#TULjrb1vFKzSiA=8i@ajAO=VwCWOc~Cp33%v z$;fYJQb&F>mG1osJS5E(`47xIM>D@-d;cbT^UCjS*zEE7-0N56ce!`OaIIN5whz4Y z4~Ud1p-Nj|4_aLnKml?8jl3>T_hp~L0bv5Lzdg@B~=Tv#XO z#cqu4){Rqkw_vSPwsy*{p0bUxy}mZKmzPi3I-2Vz6qToJ`NY9{##!nl&MGP&pvtX{ z_rOGUgsU%S$2Q(JcaH7PaZK#l+{GFz@`nJDPD$Amjb%hnfjm4&!bspKv0Jwa_GT_V zt=--hDP804Xqt_tcG>s`vx`#ewz;6HJFOXTTy3mff01uA$L{+2`iH0N%ax`rZ(^jp zN>h8+)Y>(*F|IZ4s!y(|=6a{;7Y=UFvH@}7cH@-GE2g=V#i^vT568=JtMG)1!hvYk z${fhzf~Au3Tfw4&?Q|+i54+vMi+aPfuL{>Pl+27=DbJs8j>X}8Dv}Vpo|MqUihl#jDU5awH3q#D$ O#_4!*sqQcO_5T7Ln{Flm diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/functools.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/functools.cpython-37.pyc deleted file mode 100644 index 4936babfcf4e6a873120b0a36640fd845e1f92ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24274 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/genericpath.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/genericpath.cpython-37.pyc deleted file mode 100644 index 7d3090ab383237301e0629e46994ed78ffd9c62d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3947 zcmcIn&2JmW72nxiE?3ltWySGF(-s4xM!bPb#%|I8PMW5%Y{M6)umm_DQW49Yp|s+1 zcRe$7L}A%O)n3~ki=J$tm;OP$?6s%-3qAGsW<^<1tQK)mk~43<=gs^0y~od2S33?q z?w_9Ry#JQt{F6G1&oUaHq3FM&5>DR{Ot=~AGfUmRD?H(gmIy>!gkni_#IjfstGmm6 zPpk?5_fFpz7eoiNCDz3fXdo_%5VS2eL>n{|Z;2M@lDH%S(2jUpc%aMTvRDOO5m&@A z=&HCXRzTOpHSq(`3*sH|L(p~MZaLA94*$~mb!_%{QA!n?w8%A2ipiwNxheRhP?DRy zIOjz!`4?NA&4TBJ;ZrTSNR>=XHtTY}y+@N=moiC5X@YHHnn}&mNm(d^10;{jQWd32 zVkD8oo^sH=W)H#uv02IN)PHl9;DjnI^2~8>`tU@ z;ke`0#J1X))#;(ETd4-0b&%>&nqjSuCpZSJ6>8zl`Kxh_0~1D<;zKkFXm`u`(y7iPtC|^OEG-@C{)-k!GqO zs5+*&4n9JCT!%xf40PkIpMO&DnW!GVFy{ zv3>s~q!zh{H(n<%*hI{g+?{5z;-sVpQA@4j0<}if1ypr=Yw&36$^D0QTblulPDZXG zW@}d)E1ss>pbbl?-a+|)KID@|x7?_yG;rsWf>N+{s!)n(rQaQK4qt z^WL}l=!v=n#v`|8TD?tgA6C9mPd z2(l-c-vZa||ozqP^ES%~ijTR|(ajzx3F#ftYTI+e4J zr|&ysx44WpLz|5o$N%tKz-zuPIQcgpPDd81EMiGK$^sb$ObZGCq5xi$=7ps~J_qa) z{wRu*XE`Uld5WS*=Z?Gbic=c!P%NiEMq>d>bJw=mOE&k6OA0+|`2ELs_&w2G1Fzp^ zHcrem&MeOyVYW$F0JWVC$7h?;4*Y~PQb8*X#*yanq7;vYdWICgbHUS}=7=t*M(hbH zPBpR|3+IU}DWxIQr)+6~lst*E49OFhsZ9nJ{PIzpX2@}fk<(zRNL-QMcSpBT?wl`H z3dcJrngGiQI;``*2=?xG1WT#WvE+u7J?Pg7n9%;1`?@tE+gb4Mjmq17RR7@xlp&8# zUf|jnSR26@MYI!)_#--%^8!W;gMfdl>$c~j*D?$q-#T(JPAfc&1yxY_V_*HY@&&u% z%-aW_RqZMmJF2Q2wAwUEs8D%82}PJw1-9>0fpDocg1OPUkFfjMr$7#iOu}Lb%>hOJ zwpC_nliJDyBXdp4x9Mz??@Yi;(0v`32HYU=v8IksFZxAv3$h zk;4@V%dCkkzz2);sTA`1O;r@;7P1KwUH_N}pTsjh#1WIy%(~xLfU+dTF3ZFgR?6do%%% z)9x@I_Su1sLpMb061&P)T=fCwPBH-s3sfGW=pib>d}j_&Klr>NfWJHU5g>fSj$i=7 zox9JFkfV=4q3)pXq3;3kF}9D8F>)^>R0!vHSO*2VYNztl4p#Whs6bGNT8|%WAHH`( z-;8*yc7et@1UQ8cd;ftpm}JAyq|I-EaGY2Wcnu& zLPvojT!WyEs#|tdy|g_mrA_4_t3d+Y>%pK72LrO0!60h&L;8P2z1jy?x*zOejZys& z)SjWP;Lx*zUmqlUG8qrBWngfH{xb>Eh6@A<@~(i2>$A(~tB)}oU98)Kfhdx};B-1S z7yz>{MA&T8W<~C(D1}pmHi|q`k**X48|(6l@JNwMTdmsTPjP4yR!YO`@RR1x;it4; glP&rb#jN`Wt#CP9375i_{RZJi*bZ02weZTn0T>?9nE(I) diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/hashlib.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/hashlib.cpython-37.pyc deleted file mode 100644 index 5d2a35a3b7339bb1afdbad02ef6c3fe474913be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6634 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 Or{NT;z+Ki0>i+<_an+Up diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/heapq.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/heapq.cpython-37.pyc deleted file mode 100644 index 2710c43bb472a1570719f30c70bdfd9ed4aff126..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14405 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 HxlaEE-dqgi diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/linecache.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/linecache.cpython-37.pyc deleted file mode 100644 index b3601ab3767d72c71a8e063fed8a27cffc2c2748..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3832 zcmZWs&2JmW6`$D;a=D^p`J;{%IL;QW6F!pci%r6_l4{)m#jbK|$aA75Ui<@6-%QCW@@6ZR9nRf}0z7j@x0VOyS97M^I}X+xY9zHlM=;+$9zO-Ku3Q7mCpQ&{&| z>-_#d?u6Yz6eMvPsh}sbQSi}J53)2+*+h1upcf~RTJ`zev)m6i7H%U_`fo_2qiBcwFlWK zYEQF%JC0-B8MH&C;(j`cQmxtoo%UE}J5g7g&UfE!E7@&thutACX+MtA$L%EEZjTLu z-&uVRy)-gsUmZ`Sg(c45RvsG0eSVoYtuD#)i%w#ULL=Z(a77%^+F!Xt1~s@CZ2|TZ z%P5(yZnSvenrG$&r$R< z5AFFgVUgW|y9KQH0qpNEZ4Z6s!#yn)g#>5jI1R#-Y$2ycxuzH)$b&GU*qE+L7iW7; zr`~9}l8i6u*u}!cs5k2s3qOrUnVkMe%1j!IwQSj-p$jzBHTqvQY#pz@iCdjR!yJ!$ zya_Zdpt{6sT+;h4!ATb_NeYd%{{|rkutQH?)J*e3>xdoj8BZ?&0}c${$yuNJ4uSvK zZ*qQ@efoHYcNH?WLB<+d@+Z4%x%J4I*)wP6&T2VkKd5ueo`u=FyJ zssX9rRY*b8Ew;DzOO{#>8KSDbQy<#uFn1t%KzxnXy2W~g;0)niB@7kQNh-eH2fQ}|(@LB{~fSM$EtF>X^X*CKbiIq0+6wWZ3 zsuCnCQ-z~+sEhi~?i+N9y3!pL??;6PVWi_x)bb2gMPnZ7N}h*>F_DJ3W{hmo6R$T( z5+Vcn8oI9nN}TjP-0B@P1n80lP%X#u30eT##IJ?Vk^$J`7x-~Bk)IHM7<~T))T?N^ zqInrlRU}=Z-Ywkn-JBg-!aCyeCL~+fBvI_-h`s5uK@V?d_5=2er?nElXIyTU2x63@ z>t!6ue@@Sps|aU>9k7`T#4llnr)xb6sDDw;0ov<8+Z8T+k*}Q{|8OB^*y(?0_Gde~x#Pn(AI)mm0li(!;e$uk%&L5D zNuQw|VBc5DJ?yUsU} z+!333@KN{Y>|?MFR=s$v=MSZxl8v8%{j63h~}(tfywFlIC9W^_Tp% zB+}V9rXHd`a_#%L6)GQ?GiRSRXGpVxy~h4%?K(IXFSu_40!h?bU88tRqgNv2rN2(c z>Sm+y?OoDFs%vcj%~Mpmx}IbRZFL*Me5_o?xaa@FCEtS7`o<|5_7UAutG!qc3J)pN zNb(|vl`(n=Qqf4l{b|M2ADGIfk`Hr$u9PI*!WW zOYdtfLV-oUNbSdAeU!Y;G$Cr^UE^)_lKrPGoIF1kL96mM6vmKDo z>sHfgVnowCzknx{Woj7fgPe$%E*dS=F5#B6#xXb5&>;sf-1K`06*mQ6;U-I7HWd}} zHrVO=hMgQl`nq8!mn6#RIhRjGEvGE?H0OtosDq;{xKa%@gRR}%rposK`6#zA!jVsP z?XZr#Vu2Oh-0c}YTraCPsuBF~zwp=l5!JKv{BKhEoXt_1qVoJ|(S~Z6Dum6GDmBSM z5y`TQ-A49TLnx$jm6TS6be1O5U=QVRFs~9(P8&s(j3N}ml&a#83Zo0 zAjhG$IIcEOd7SLGDmF|dU6s~hqA^8ODsGn4a5LDHld2XcpGL)v`W-W5)JL??1eEtD zip!v&y;w!TJw#Wu8f;SWUrq|t1PL`Pm4Qjje*n`n7J>Cbb4t>KlXog}5EW%2 z7)`)bFj@6qfDUzR`uV$(>cZ_LI#x6vbKNlC*JqI_35c=`E2$FJpgowJzj;r-315@} zn!@jNN&q{Z!s~P>k|6mfo83T?Kd#**C1`n-CfXQc{&j>1ZBzi0w5ziWRegO7T8YD? zRXd5_!m0iU7+;a}w_~e8Ym_nnN}OK9>p$UE6!mP8;*?^PBDIO=qmqCsKA$^W(%2S9 zB|iTy7WGa?WZh0j-oiV1gBrtX--1Lh;c<9L3|bz{CW&fBNwI1o*r+{4A7+EZA%(YI cf_$4|TMH`e#R9toK#HO$+LqU{WD&9mzD0_XC4wMGLIgpI0QFeQzFO>D081=( zm-p_H#0GS1Q+~uxIdPoCaU9Z#6WejqG)84$ZCcmaIBn9TZJhL(CT*%d z((iBXz59R_yK(wQ`}vgMnKLtY?mW(%IdkUB+}RUbwhYJkm-z6Nx7PN@W52CH^zU3E z7CTPBKQt1HnOGra;wDjv7vdHt3JHsoAx;%iHat)m04FQywZTFr9=tPD7&0j{VA5vL zWXzBmHd&K1Tg-?VHDhM0*=FuA+s&P3hq=q_GkD_7`wH95{e?Tt8wxwz zy9zta17?_f?tUp@zTfONnHS@QUC+g;iDzRb=f3J@Y<1B4JvUc)waJE|KX$W)*SL2V z?kUF#uXTrR<=uO3$IZBMxfw6qZ5}jlB)`{@->1zUGeLg$n!RQpaj$n%x9&6hZ^sMw z^YjPI0dtV2Z@~Y9=8)Nn{{j4;F^A0<{@wULYmS(0_{YsrvxOW6%_HU*_(AuLOL6n4 z8R6MO<}ou$+#d5L^Ei0I-Bs9Yo-oJp?=zF;1bDxhGIxLvn3HB2e9)XSr@@CP<8x-l z43N)ZcN=*=X;SzfCjN)a*?=1E81b`ai1;IJ{PNLTkC=0}<1Zz=9H~BU=1iI=$Ep|C zGw!2t^}=KH!egt$q_`0DgZm~oZqDCK5ObV&{(`v>zM~v|*gO@4p!&$OF=GCrxfsNl zdHxp6CH|f^&zNV;bEZJ}&E|RY7O?)_Y8>-|DH2{JzGMu~T(e}B%?fXo&1K$PH5IdF zs-|Y@VIEgL@lfIM>j&H?+{bSnzfHfLjJ@UF=M#m=!U=cs)|By#f140bPr8%tiQ9=d z^}6y4&%{i_{x!{2bIn}mZ{4)aH}SV&ZkV^3Z|3jq<{jpp=B9bkyvw}XyvMxPe2aOX zdB6F9`Jnlb`LKD(e8hY!>AsD>kD6~cAG3eoVZPIRm-)DLzuSDme2@7gf8T3vncL=5 z=KJ8yPs1@k$lqu9`z*coIiCLz^!dD{(gsu&wSE}t{jm8F^Owwzg8wr0`Z4q4=C7Ea zFh6Pjs`)AN*X-Y4H$QFu27f{5Z<^rmXUyL+KWl!@{EYd6`P=5_!GFj6UGw+MFPOh? z{sDi#Xnx83GVm+p`VY-NGQVp6vH2(Fi{_u2FPUF6ZS(8q%jP%CKQsT_{HFOW;x^2` zFu!en$NWq4uL%8X!it**e%E}({GR!J@V_zt*8Ds3@6CTO|Iz$``A_B#iTNY*pUr0;7(xa-1Pq6e1?SA?akl^p zjf7Z!K@>lVe+<|PYzyHIuwc6Y>impoh5t@q2VkF@U&416urq|a!MlK0^}ws~NAMc_ z_Xy}6{_wpP$OEtIfqU`49=H##vehRo4!aP{809*o|4&fQF z;MowK0~a(d!EXkh2i^j_6>xwT%-_W=GKz#3Lnwg_AlwTsVZl-eN+ZyF%OR|Q%fRIj zR>74J*1%Pu2GoHofEQvPENJvV6aQ7o4e+%Pu7hoSh}Xd_;G2421Ha%#822{tH;3?c z@H>Ea0yjf=5&SOT-N1W*_lEde!0)p>FQ1;gANT<9!4N(a;tzubF99D3aTHeEw*ub= zd=&V0;A6md2#_cL2K=2Nd>8oRA$&LZ6M)K=|9b#EQ$3>kd@}Ugyzna=y)XQ|A>0BB zZUdhR@%MqhKlFbZ`~#cd2MK=$_-qKD0}FmAgwKNo3jYP*hk?Hc{0Q)ufFBLvFM|a? z2K+eiSAd@g@lS#Uf3*jGDtz|Wz<)i2p9cT5E#+_E`Ld&}pRC zpffRJC77`i%vcFC0HlFIAOj2mXidyR2_wyD3ortV0%O2dU|Wdq0B;BG1a<&-0XqTd zvAcj*0j~yL1Kb0=7RUqAOYa3<58MYx6O{%k%~KlZIPf6wM&Kb}4=@qJUhqC(KX3pz z2uOoG3`k=<0vrV%0geHW0*?W20v-pR0FDEbzzJXqI0;Mxr-0MI8DIu@5;zOY0_T7^ z;5={vcnY`(%mWL+CE#h`8Q@vqIiLW%8F(Ie3-DIJ0bT%#z#>or4B!Gwz;X{>!CwY0 z1FJvluJdgu0P;-wL9pQ~Q_ z)J?@cd6V^)d)m5zU(dd;=h=jwnZ$f-_m8lGEPf&$i_O+b#fqEvoAr9lYvk8zrde?( zhKCnc+%S-@d$p@&fSC>T*6v>gTVy6*A?mD34;LT=bQ~tuB|Vu1YG^ z*6I~^&8;?uDb$ZDxjALITBnH+|Pc1yze{q@}jQYsES( zT5;D@*wtdCY4a#Iii^-knbeEEt`0nxiQnOlWlxx+A{7hrGSn+H5PIZjC zRBTonG^kWFw9L187HM}_(M@%t55A)H{@i%Ho%9=CduTZ-s6B=^%r7Xqy`7l4=PtRP z=bEU9_Q15~)p)a0#dg+%a$$Yj!@sskRnR8O2vAvFL`So91?4%ijCTmb<6E^ z&~fc80d{zUcC<64CWTf@>+PYcdbUz-x$VsClry#P+=c1(uzcrdXD1h?+k^NQX3kBw zvv|&(pPOEoy!f0=F?Z?Q^u?K}cA5v1v$O5Y)S1bP&bi5FOR9$c2`7Omz#qfeh;77I zQ`U{`jLpZ!$Z7rnbF+&V8mw|Aws=I&juE$=Ot%ME8`uUKTcDkk;!8UlM6JeS>4 z!v+pLyw~?idl!qPRkv#PUUjQi_cC(!*4G;=wd%o%BYVRV>+9`|$g2){o!V=Okn&!G zzr>)m|AYmWASpZ>0TG^8gVci|5p3&&Hg*Yc(QP!nss>!}1ja8m@{8_D@hVgix0lxH z;TYLdyaug;cWt}j$hhAngZF9*4=Su;A0QM}__g?z`oXV!Grq5+<){u#yM#6wsGDba8}ze_;xbyTb!YsV+Xx3x3NUaeWz zU>J=CgX6ESE!HaSY}FA*IQ5!eZEvYNCEsD3mKdaddrP%1n4n;}?<*TmEo}6obxf>j*_rE;KD~_txsTK*k)q?$+J~GhPTkWl? zM}Jgy$t#u|Q(i7N{NQU0cteow3BbP(CpM6ZC%(>Kp8yb_Shm=X zX9IS?G&t5^O1l| zgJ3jj{?lwn_jbE~JUQp>rVj1+RO>+}Oz5sPEA&aNnzz$TDA)b`y;Jvwd3lfV&UoC@ zKtP^kN|d);^VZt~cEaf)o5qwki1Q5KD}5}LiD%-SQKE5^1S~mr;%UTg#%{zKac}!Z z>{g-?m!=Sigt_r#I~!Kg3j6I&?J6?`lX`D#x>+~WN8{COu8F#>0{9u6SRx%y#fRe^ zQKWhZN`QX>$HZ>Lube@y@hijF`y|#Nw;J3UD_5aZ+2o^fGM@0%`1bJAnz8MCH=gt!B&x8b zQuG^+Sis|*b|&&|YFqn`&YD1?Vq9yVG%RnkT0^tSL*qy2$p$ zAK2Xfx8rxk zHqv*gPRW~b+zd4v-Wl5-Q~k%YbKX%}?j4b{SB^Tt_S#qegnuu`^LE4(hWG71aPZLK zhmRb6#Crot#s{rXXs10*MfG;F;#Mtv+v#Gx&P3TB^iVoI-)*NZBm2gOy?c1Aor&ai zJ0+$L3bq}eu^H7}Q^B9w}c#K){J5#Ju)CRT}O5@T`iJnwY4L(`nVa)$zcu zI~Xg~jKcCU0^*iJY42?&sZnz)W>UA~HwHHn-o-|IW6(fBXf*J_#PbP-9%F1Z5;uwS z-fGhI7tA1|EyGAiZVd9?z((5pkw$6*d^15w8nY@Pvr4=zA>nf=qnPZR*~! zL?)55e4UE#g!j{McnYjIp4ungCDL~KYM6lf%X0fRgm!~D=~iL`nR7FKBZWU{;)I|i zG>ta~E<;tXiZn}K|Kdi98RIBDHF#_AHsb;+Cm9 z-qjQKy*_I59KMgZniZop>_c`rv)F9p8^u+vWk?yQpN&X$Vals%v91x$ zf)Xt!e>zlE^JPk|!(XgB%S-m<#!A^UU2Rt>8eTKh{HKtyj9Y0pll+rwqlHosA3k;9U}3mrblk*K46E?J4oN&xMW`K+sb z!WCAQz5$IJjgdaa`n@r*1MX12qkV7&sR=TYZ7pyRnC|u-eEf zp14`!cGCrqLse?{)zj`OADb^@pAmJm*bCnhn4jk<-i~@Z$i!AU%`CMPEvLy@KIl zJm(d8Qb-2|k#K2d*J4$>SVpYQ*#v=kA<#;b{@NlkHnfx=N`t8dJth;`EzoGNU~C>W zV`PQMi}|X4ESXLsGUJ)#&O{D9eGDyqJ9tN8dqTbp`ulL_PyUe<0#+2#Kj9>xmif|a zur#2$+*Ic$T1SH!v5{Y@)Ucf~(FUfphcq42-F8Y1Edzb?aBJZHiTwwb=^xECAkk-Y zJ7nqDr*>G=U$;(Dg9WxuQW))0GtLqKl~hY@?;b558O{k#Z|2R z$V-tlnZSUQBymv1xUJ&m%59+%XL>3}(Ed~9q&iqGI)O)(Gx3`ovSM0bA<7hy#F)g? zV5Fw2+EOGqD2O5(#iyfqYoZwpEMjPHrhMlwzIo8figu#xFTeI(zyH)v-ZONZX>gFT zyu0K`2Vyyb>Am5pns&dz6E&I96aM~9O=%A}nC2R@YK(?r4695|%agcwjZlXlG&VXd zdx?NXEDN<)(-QcCr67heYw}1`Y1a)5Wh_pJyOC_fFDEZcRZ8B%@Uf9(oG@-s+ih6> zMw*+PXv>&9x@Dtifj*}m=qbW?Ihbh?E&`VP;~DM_@a}_v5CBJ)L|PjY{zu6$W)5e zWo>$4L1z8Yd22Jdx1vp3`Q1tJR*_zomlzTiDVi8gj95E}%wp;cSw=Dm?_H$m>yFOw zlnx|8#r%EBup-1pwUchaRw4TrU6Z&Se?EC5!5_pnDTsYYf=cUZy`%910|wSIt-b<+ zX6D){x5-AAgib3vF*ASu=+VQE?Ad=9DLvc`wFWLNoZ54=HPngfefo0zI0I@(>tnlm zw(Y=3@(wbUttqfuc-IMf@08Q8uCcrbtW{2wv?+Q8W)e|IRwIcqXchO~M+Ti~MyutH zNdGc#i5A%ZpcFe?V%_*H{8peN&TZVo#Mxnb8ym(A>`B-K2W~KQ?bCvN3N@wEiP=e$ zyph620-KW#7H5@^@;3lcE}wfNz$8hh?b0jDSwj6LFnd6V~}lw$8~-b^cN($InFX-O#G(tLks_ zmc^*shA%~L*pe~q`TLn^!cn#oi zJ+I&b={&om*WE<6nV>NS>mgQb^4Ue(wQ^&nlT&xEWV|QCnWav(f(?zOV!7g@*-%go zn`#;3lC6Yn1X0PIJeeg|kTS06&#~K@NE+#FX|$`=+O=wsd$fa|5BIk*LDV`KD~B+? zvyX0@r3c~kXxn{RYrjf)m4gk@Zujo-PBy0IvXf_nFUOBrvEjW(Lt5r&E0pH~9d}(} zjd*4*ZD3lV>OF<8oeQOIAZ*{JhZ@v@)EJ7k*40l|f_UGehd1R&coeJ{mT2`}R4`kq z)mEEzN9hY`nurkDBw)O)Bz(JM$_sd6TP15HaknKTQ+DE}k}?`d4hPn`Kq9A-Y0_y6 zV>rHxG_qW$ZJJ>W4KguoO9UwbO?V8Qcw1NBl<@8dCp9zBt~$c$XjeD|159RYg!NH_ zkqiOP^I(I+hST2DY#d0OVX}*alN2ISWq51R3|ap${;J8&qiLAj1_oX&SWTMYv!(b2 z4WCe}+uZMB@t|WwNo$4*xYJt4It;+hzm8&{>{>fdezzvYW^oz&8AI=(4sZ1iiG>b} z*{m(+b_TBOT{<4ZC~K@>U|U}4(f&KdT3!iHv`pkD^G|oStn4rsj2+_BM(13kq=~ysvV8R-U5`n z_DcII!x~pdV!GuUZHcdOI>#Ur@*EN9WYMhJ5gnYPfKuh?VQ{22BdCTxupJ4U^?$|n_<9l;OE{|-5JByO6# zx3aeZF~i+Zb?~ohr0pbqY(yiC-5*wlnfQ)i4rio!AL3bO4%aZzJg(Aw*@V{jZD`hI zX0{qn#@k^uSE2~A>v^x8E1AoqIS9-3y(z1NFD3YP=3;R2i{&Pk8WVqKBK#UgOPYb! zi}@4Ha)lo4oR$hE46nw~CAc)0F{fQrY0u6E2freVn^@-|Y8S1C#T~3`;1+w93Nv5tv70@6@_)+k(+X#3VZ9z~>xMlk zS*c@Ywtayd)yRECoouVKC`$Eo>mR9Gb$B3_NzkocgtrtF<3f3pm+zP4L z$+^=UX2QKRd3w6j-P#53boWmZSl<~MUr~p&c}v%$a?!0j>DELeX}gv6y#DCSqtC_~ zsmp;u?giHD0PBd9R5h#WzR*bD8pI$AyWB*L)4HB*2NYjh%8-nEmxnJ8-Wa&fs-7*A z2T|WJ>#~)e&<2P1HvDO1=nt@=ku_{$S?j>yh1iw1v7yf9aU-`eXcwYG#V^9U`2~C6 z0TIy|)RvW^$u=N)XSv@iSUW5Q>#hCSMCxSkfvXGW=VzW3*Kpione#UJYb)i_N`3_) zEqOK zQ=14;3~YJQy?A0p;G*_x+`L!?1F~0E!4vs;&i}a_Z_Jxo^??SvI#p{a(i-36uwGYW zN-47$^cw~vk}HeGO4H8=XH0_W!5-Ht*St=fLffMDjyPXb^2&?I=Hem-_ug5e#&Jk0 z05A)14z5vNEVIqHj*Xr=)My1~9XZG%%@LhX)VJqZc+e@SubFnEh{d^f1+*Q7Tw-G; z&p3|=;fF%0hi)8xuNCafB}ROT1}I$e{g33g;6iU=I;Aatt0{)3rd`UIdIt??u~8G)XBnm7SiulxN}GaIZHW?PNnITe(%NKsKhgT0j})5!F7>bRSTg zALt?E^!1WkS6#iJSF9`2O?r_INjXutkE+{wlgDw>a@85Us|n`;kT zD_0L5uo`V4vG2O~t;Blomt&{aE$zWjKo+(-kSC;MFy!0WnKccg;2`P9WP>9bba5b& z*<)Mx+nI=0+9MQXYS;WQJI`vxJ_WTCH4MUZRoSamgSlC==Xj=|NU?$UQPs!J&vtSB zalMrewBkZ0>WE+#@1MIpX{W;p#QJ@BVmlKEbt}%3_aw%W8H|R~e6?#WYp=B5juhu5 zd#rQ{Y)E%{~cY^M`y~Y5i!=<5VGL_hwavs#aRnujs%d%x47wti0i7EZ-9V0xp z=X3vG;^&v+kG8rb3>p|MAv=etu`~~Jj4?dp9L(h(rh~1%h9&n+@>^|i6CW`R#-0!# z*&}XS0((uzkR@JG3d<|vG`7Ze!7uR!Gqk@;bG&#%+x)VZ;@2)gyeO+#e%?ju(@Wtr z+RqwMucDMMbkhW*zr!TOjxzN%G^ze&jGd%AdR}l?KwN;hl7iOL@iU=jhDOP5EE13n zSs4tFzkv$ZJE?|kh&07c4TFRFG-5XVq98g|O_t%($duX7(IzYziyZd5fu4Fqlwf|c z{2dG(6o6M`^k@ms{!@YeXy>f5$Jo9 z+Z}z(M*m1FGNN6N1iZ0^* zSf-ssz;_7KHzMw_gt;8Q%qQt0h^*oj+0Nr^n6lQl3zz-Dsq0|2WCxy6ieGzYw4F)X zQ-fu-vEOLW&WUi%7aS-!MNfYR<+KNuDn&NshnkJ0qcXR;oB>&^)uJIkKpIvKIaBMA z1K&^N=5ANQs+wmooZjE&??dkV^0S(92ha+V3AT5>M^S;^Uz0g?my2TN&=l^#qt zgcG#BUg+pPey0yqHPs#Z{IU)w5Of4@Yu{pd_^WU!KYlkOhxAJsW zvS&6{4(bR?h!^nm5~9OTG4Es})!ec?AwrkR%T3NgaZ;p1Krv3RM|NsFvzdOD zKke?A7M}KixMvwT6>yWD7t*zgL4t8q)*7&0iN^02jdzhapmDIkO`!Rp`&ccA-3O_C zJ-Z-<)RQywM+yUOv-ISJR{HGunWKBA3hAi}`wtx6AL7Fyez^PIfv)#(??y_Ge_xM( ze~UUW|5rg0@`@+qe+o zONI2sv-|fQIy(MPJ9+5fk#@Y)PPo-V@^YC2u{cKxsUjco6b4pn<)fv-=vukt)%@C0 zqg1yf+7xkkbBc!x12Spt572=CK~Wod*!uyxqdllE2dd8g_7D~@J;2N9wa~k-$KM-& zuqXadkNMBHPmXS zIgQm2hW2`7@v7GzKwdjX+i6kJ@d^QMgt$q3OP$b82UHF5;SfI@?7Zz3>*k6rXRSPWr>)+I1z02*}y^=7%eV2g~^_zx#F_tT$t{pU3E^M=>*oC>CTI8 z)wwj^^Ws>s>P+`U9Hvs$x-&D^DamstyCpqLEs2=!m zF!NN;QK7S4Eucc}3NppYI{e{N^GT z=6aH=9nbYrDqHls&EBeSIyO^&z0~c*v4AEyA;fIzp6Y)cC(REHdHxUT8*47|o zS>?DLfvxP~vUB2eSX)xBIfZlGkmt}v0cY{d;|s-3$i5cln_FC2?ADo3ZBuCOLik>G zvFtp3sS~I=CrdChne1(!B2H{hG1VRa!7KeF;g#8$utIu&_EJxgsJG>wUaeM~x!In_qeS$Tmo-`6Q|v!%`DQX2N24&& zWN+;i(N{ei(G^xIv)a#yis&P{IP+xGVS3u%M?{?I>mwp&dRwLUXL{dfOhsZN;QP7W z`pAtbUD`)!K>pSPV?G0X;o7t4dg{c9t7YiT38 zJRM{@|MaF;`m_MOa%uA`PxqEGwrMD-6%d3)>(YuZQ$#s;w3Hp1m+*I^*^8ifTFw-C_O+5!W{H$?CduHWKvN%A#01pyOC&*}2ps#`m?dm9oZ0@K}Kk zYv(HE%iSR`R%tl1Jt7RTTVXnjRJ+ki&6%B?ICp7wdUo>s9_EK2V&=rTJ!p{o4<01u zsx#Xod=9p9l|T^+3eT+-m%F4O)T0d8P)Ebetu49ExlWtbmYs7wZ9-tIp&NBnFV?b7 z-%OWVD_?Pttx>U;VU(zIM%PxIbKNiN)cg{s4C|70e)m8I!Ye7faO32@qsj=Fi-?l5p@> zyZx1|BT^$GD{$d#)WmwR?o39HayAsT%7&(*&}iNCuWl95BjA_{>noa5B7vz0CYkOC zMxU-XoD1DPQ;LRjqC4;uVXM>4BU?w;I2G0QO0(5n#PQ7tqbaKUs8@3?b}5WR^_pD@ zNBK5buC<1=KN(}G9gGXN`k4bc!z%eO8){S=ZjxEOz*FtLq!5U>zAF` zPCxt13|&iwzv|3)homyDIP+Z%A&BTJI_s}F&vbN4She4pLPSsQNaJ3{9OdbJw`=I- z{)WNn{uOTY>97u+M+8D6phLEYP%Tl7n%O7OYP=_kH(78;(l-}82^ZX>zTY>(D7LXV z;;J*>U-hefsuS5?Q{$qFU2_&9iIDSKmfeF#TN;*!7Ob+soItSK84cEo9mdHvdenwo zW7%1FGO}8YHCWa5j3}1rK@3*QhY##is7H8Z8|AJNWCIZ+gl;wF7Q8XHN4j7wPL@Do4ZzYr6C0`5<)GFD4e|p zi$|hh^!iF430t}KvZ`ro20hoA93l$l)|;-Dpkb!#&1+ri<^l`H^5TJm`wz5+gPDD? zyv%sP&r9;JtokLtrKBt-PoJsk4VMVD(9tzNUJvKXLsi`Ih7YAW7yt^^@JM8-z? zd~?k+KX{=LWWDZkT?pq3%h>LVO5m%CX;}+xl`#?0xtYYHD+65%14^xW^`Hi zNS0Wn)!6nHi-n=ZW<|;`U6z({kE?z@E4z87v}Z{-wXL)UOA~el+`E&H%4*k9!d{f~vM*sy3Z z2=R&{!)N72i_a6CN;%{P`DvPQn+>0oY1!k{d8Wy?;H?phI%FmKsLCaoi*rMb1%cjrKeZ*ItB5WlD%Yal*AqEmiodhzgyb7v>^~4V~ z^kik#qH^$7Sp^3C2C4=bS0NUm`ijlN4|zdRevqIUM+6UG zMS@ilu4>Q>%4}-zCzi+?3sKp_up!E&vT0hif0p!&5 zB1BMPg=(USl`HM^io58!ih`ini^|p3h(%O@BN5mfcnho1(&a)Ddl3PapUQj%$|B%E znH6p#Yxt{lg=|P70hXf`YPLepVmAT}tu(8l@E*WcR9vGJp@|}=aVh6$AyI~2*ox?t zp>oMZ&T_vYAKF4FRst3++wqJ|s8r+uOv%=A*?0{rMzAcE{gyVD!!Iqc{&f6@ThRtI zW{GG6nolY1X0H=&Oe=lpKTQ5~CWKA%d`!P)8%?=$Rb&OTDibW`)kIH9@I8Tl1EwZ?RM~?%H~5tUtQ$Z;tU`ec899%q(ouSf^!qANDpjTs|aeWSj(Czhy65o43k1m-#!qhzllR9;*QBSwMN;Q5pl=LdL?Y@=i#h`AxYWC1rL|*Ibo7?)*S+S7Q^}C#VP|5#O=4Z5 zGK@$93B=w&6|q|5LZYy+L=E1@-XtlGVM+4|Xw~IZwqh)e2CylK>YA%CB8i@$I*O9) zMidxe`cmN%^r|CnFcV3JftbJ&%q#=gi9iV{WLStm>3U65ePLLq$eYW2LFN{=cKyzx zS8O3%2Xuew^%ki>dziBikO}HBHY4#TmLirai8@ustR&?ZL?|t*5ff`#_9At)2M1#< z0%iCdD&Xz}4I98L6e1~mMrFD<%pvtAzAOVhDh{z}#e(Mg4I&HVlTEjN7n~qOpmE2GKeumHCC)Ws_8acHOEfSePW#8W0FmlGkjFSVX0Cwc5JZ+G4}UL)%heko&||MV|qT zOe~=jTCQMXV$7$S)$-NCkX){@L(1OK@!D=X-Yoft3Tc_0B+QyrNXjZT1~IG?O(uJ! zO|#V+v8bmnQP>BtJgKTz={amoSDDW(nrM{pk97Tqk6`eTIqGV4;;PjgTcf?9{rmS9 z64#&*HY(vOtcJEH`-;D8lljXN%ZrebWQ}V!rg2R#+QT`4S953! zL5opJ{cBI!!M!s6qJYE2r!Eq!O%4zT!X_=6dCH>c(-zG>XVJ-mMdyMf3v)Jf{+vb6 zOqVuphX_DADPWQ6L`cO8 zDT$5*Safa*q)mUj))H;)?l3LY87YhO0-;GN1JZj!GZe3LM!cZyVY@g})$Be#NPG4m zZ6kuT$<7KwyW}A4joYP$s$@?Y5YjHVMJms3W0Q5zT)Q7lXoYQOX%P+QG)e7lkq)G4 zmzk&9dIo8K*eb@eWN!Cmt+G42KzG@r00gydjB2UPpDK+Hm zo)AczM;6%zuhS&5u{%0UVrwmqIuH!nYd1XzY3~Q5eI8^;jRSWUsblTl3P`&(%qrRt z0ck4)LC;XsIAPkk08K#3hR(V~5zG`%6S4;q?OZTV$nHtdN5vH@(aL3;o!yE+6ls%S z{8!2k^L<76)pA~x^Hw==>+sPD`oS zl~S!zO3Zh4vGPql-DMp;7?3Y5=L2$FId@n`84SrcWPQqNNN)@&t06UTNDUlPU54(H zvs;cDIHU#+sewak*3d~gXK?OUen;gPIaxV5>!^&J%E+mVoXW_lj72?tTFwzUgVs^v zK_wnk;z1?O=s``+X*nx$w#a!z&WM~*Ij@uR7V9XN$K;GDI40j#`OeCDLe9LLcguN? zoM+^0lXG0of}A(Vc|gvDGN{V8SI*@@^A0&JIdgJ0beA6NQgD~j?b6dX>p?}%0XeUdbDx}H>nPo@UK>_H!zzf2?QxXLu*w*| zPtI;R56Rgl=a8JEavqZ-RvA7i=Zu_LITz$C;7qEZ*H}lT73AA3$5C)bzLRpElyi@q zr}W?{`CcpMgq*j_xmV7FoV<0EZc4r>`5u(-qMY~2IV9&@a<0p{EaxyzDHi_ICyxUA z+11bUjZ&Fkk=TeWab<)_yr^5N<2U){P4~3DiBGb0BMBD)a!rNBJPWS6ASS($s2?|j z_7XuZnb=6y=c15uAjMGcyVqyA=PYqM#`P7)$s@&m;N1CTxVxLQN&W6YC+93Ve>}>I z3xSgL&qN{RtluusHJG-HExlzlQi{EPp;OYyuV2zj@jADrg{`10!aJg{E$z$C#Q5}V zppiBsO2wyV_XVGv(ZbQN^sx|c73RW^3KxDvHQd%)!|NA2bvyOHRku$?brBt?+mA+J z)$OJDmFryaaR(o_ZEtPQFR+Wy{Y@(S)oABa#w2|XA8-L0AB@4tvFj76p)N0>NAlDq zxVwf=9PPCv`i+7d*O2f@-D9yUIZEMG{VvDrdAE?{Yiz!`99*u{7Wv()Hp-W~=JUHF z!{HaO{GLiXzS@po-Sp8K_vV$^-ocb%zlfJgNetz8f_?6Fx`@f<6>ThO`wa)DMKlHCPJR4rXbS&S>?&cPY;Chhp z*6?)r!(TjjRai+rfVCF`^MNy8T66PYvwp0VoS2wsZQ0HOAhlZ zH+q`pZXm_!2SA1s`jj$=9|@m#pL)MZ&cSb+P0!DBU(h_iisk6C6~}3fg?$!%IDf3Q zZEo}L;T;=~^K);f#uKNykX#@T_dY___9^!|NB_@qa|hdzCC3TACjBPT6t+T;;0NX= zY*CE6gy(v1R@E}P4hfF)gUeRGS8+r3#=TmNK}&9YUruhX;eq#BIUkkt?Q)n8!<$?0 zkk5Xl`djkdDMvq*<87Ctc_jFJReOcOg|AYn|zm*7_} zm@oMjQrFV(<+Z(B-MggJx-Hh;i0+NacSXtg44h*D_R84c23cJM8+_RQF8SE+XPb3q9}cdL`{+ z&2~+|sK2hkLc%z#E{(jm(iUj-0G)${nD9qg4?Y}VChYNiOkMzL%R6{NTyP$#I}*lSnjo% z>~J!-Gk1S(G`A;{A|@r567I@mGxM2yGk4|==eFgx=7vWSBf2IF#?K{3Qroh*`@Y7n zbtS*Xv#;|TUzzj{TC?rOH=e`)fAh~r0sRi!ChmEK@c&+#pe9jnU;CZ@w9z}SgnQff zO3(jqj#J%x>!;A>xZdaAi2u)@Uw<9HejWb&C4T)fzL6Av)^2}9kg&{Yn0*} h#N2Z6|Np)&1-@Y_<&wE$!7Rl+wz}&U1xxiKfJdMN3-IA|=XWO5@(C-rd=q z?U}9aC3nX?LLw>_6*w}TQ;avn$-&6M2y`%VOW;EeK6L;eoFITML4f!~1W3OB zub#&aNk<5f8FW>3b#--B{r~^{kE+*3NAntf#*f!NynIX3{)KM3zvC!e#1%egXqwO} zn$Rn{Fe(OeQU2*k?#>NiD~51;$^W9`QFWOjQy3yzSaGe{knEb3-(!> ze_$p5K$j-e@NzO`2qudie( z&xq^dnwa@SubdFy7N_w>X>%rRlM}E1fq`~!tYk3iUt>OR;@c-HCv`2b`~x5BnAKs- z>g)c21p_lPq@B*}Eis3lPO91QsNcq$GnG?3>fPx|7_zL|r>l^=p_RVVesHO|y4nof zmKQAr-m34edO^Ll-teM&GYDtgTlGLR?}l?XXTR~hd&id{s>}KOwIGaqPq@tmx4znH z%BUVJy3tZSbXS{Vz2Uo}F8x~6*qlk9yUoz`0^v%3!Iy5-DSh9z;pr-)Lb0)2UDm7bvz;|39V&+LcT_KF1rV|11quj)G30Jrq zNuUw{AT2bAf`p5{cBC0 zM$3oaon30K`m>wO#o2nj9#xlSy)djV2CIG$g|h-Tvn|vNk*K)mHpK z%-->XJF|`Y{A_D8T51N*mS3C=BI>@}+Dt~PAZ2yF$txKirlH$NG(E3dhCGYXj``(K z!SmZdA=0+=SliY++GaU2Fjo_EJsxXYmH_B(8(W!e%$M&?VRi2zwC61?vZE{st&~ax z)%%gNVB9mpMr4ajtS#r3^SiZsy0AYsKGsqpwXuTPwl@bx_Zr|zm)M=8j%Gx3ge;-0Jd5XF!BO!Kc zH9R6Z4=c&t+-&(*q-@Hh_-Yi%`uuv7-kaz-$yKX0j5e%R6Q^3GsaC5b_8~KgO3qO4 zStK*K!YL%0mDdeWbKIEHC-tIk;o3pc9?KH3`y?fTVCnU}S_g#Xvaw<{Psd>7y;@{Z z%?c62Y#+MmWBzxS{AdYC<}oE)03W2c*}xpWq@|P@B&Cdep2{y!LTWrQA$-hcC0$;i zT4MNtxj49GhGVWY@_L~^dg_3#Z{Z4W;v+jp&+K?u=p92C9ccfK6%>SpyA1B^j%k z;!ShKM%f8}7-zyijGay<&UNgy4}+7jBfp59IJ06>zGZJ~afVXd|GeLhOSb$~Yzv2b z%Tk%f)3K4~C|~>VmKNL4gVSiGzM17a(v8z`2HH{MSy(Hks-gE|dk=|VM&%H@Y~)0_ z1(WT7xm5J>%OfHeYYRrK|C#YQ)}SYB1XuYv`5Y~TxW5apBk1it~+`GayE@xN8gQ>JxL>(Bne<% zKKKZ)lBBVfQzTi7ECA_gaIFrmHNdkbI5&ek8+X|bT5M%vP;1-hSg{4l>r8p{F{P~- z@?TM>i=3(hr{R9fj`0-jGvJgw+B^W?!^-70pgeel+u&(okA`-{cU(r>FCJ-Yb05D{ z7=gCvE4Ec%;LZ^$sXk#ftFf6Yu>NF`dr~#9%?DZzjixl}C1AK4WVfV{2O#*g*wH0lqisjmZyV+cKl?LXHN!=(`b6;`$rq+p8i638! z7z`VCz0J^#D$cmh?2XWYZ8`gaeKs6?_h!*dv1@129B87?)UMu^NjP8uQ8*Ht5i zHe{8$bJPpXbr~(C#&uI}x_|?y`v_{dr}q{4ADP!Itg0}Yg(cU5l9G>1a_IT+jIR?0 z!TJbD&v)0F45=Z~@KSqjcOg!BdKJ_cxk~m2!y{;u{k?CjDn<5+qgn9QnX!p z*b6&xu%I8!5WbD;<0g<0B?pK%iK~Zpq^xNkH104)vQsnP(>uDdDWFLW*cWU~bj%Gm zHs#eA`c&xC8Z@E4lEppl&S@QU?F2L+tdH1Ck;W7Tl?<(80oN>GqQ0%Sg4hBo8nFfK zmmw5_h4Rrbkfc;lkl?0humt}NeCpL3C9-BD1Qlfx-o6OA-U4`qnHdZ1r3R$puq#gj z4yN2($sQmb8C$Fr^?C{eT_(QXE0p~F8=b}7M&5+q&H`aNMNqj>ZyTx|7dUwsg#1_uGugiA)C^rV5X zP5e6tQp6zs`7r~bl^}bCSA*=c&0>$L6c?F>t!G3gyI9B5s0f_U_Z40BWqTWUShb}m z+3s$*xjNr$)N3wz^@_o7QaFQki>I`i(g^N?*MJYU0L)E;BW_F9aR)u~Lix0M_iBn< z@OIdP&c1zveH~>5TB`0w_1cX$=iW%NVN^vV#4j1j;4>f{L(D?H&2Mmpgjbqn0H!8& zyAMIMKt1Q-1a5{FXo?mH{wD%i^d}D;K`R9pmmaq$Dw+WW*(LE!Qsp%1dD(=cy>r3B zt2axgl6M3tHTgc0bT;xfRSZps;syVXOHIe1=@c;?_;-`!q2GZcwF=FqT-=^a5XSa! zHo{Gh2QWF3jxNr2F_!Vxj174?HpsUF!rCaC1+Dd3Y|5K;Y0~jEgn=AT+xlAP*3KH zCO?F#BWD^0G@R)y?g73pqRraNx3IKuJ+mOs9m<6TN8Ac-3vx)Q_D5Ws;o7Uh=Gv_M zQ~DZlI^KYj*vX_&;DFPAk#aiRQx!{zaxwQN?7iAOxDqM`1J~obcA+iHSDol1L z?I;(G#MV8`On`w%@zOgnR5#kNvq7$ADc^qc3di-_kJ$40h~j%>A7S~|YY}X5CN+#& zegIk@ef{mXu8@{p4_1Qa-2k?1lPo>5SXCJ2qlfxO4BClBZ7U=1-njD4^>^OBdhN|C z6^E*>zk2iaN{&jG-?{eQl>`CN$NHfNg+{RJ!@E$`@*+sev4rK2#r#dP!bM9xheNEsy9&e4z?A$WrKq3P=aIOMs_j+VGHnZ7GVNS^Q+yICs=nED9=V5W^oZU@5nL&t zw<3BQLvJJKOFAtpxUbE z@rW3o);f757Y~f!pU{tm?;3Kh`(5-op+?0|bPE2&1?ru?hCCnqyxaDXF~adpB`UvT zEWhcE1#m8INw3V@Fsk4n{Qv+81bDk&nis+kkS+zZf_OHjQF+iuek) zMxr8bi(E{u0RkTpDG*c;Xum%(eTs5HnAyY0BSx zg|Qz@$8O1dx=LB1=J1#?7E8|1_~0_-!4E?`y7rH^w3s%!Cff@sP9y$}XaTlf>fU?< zp>WvBY(m3V4BexspK*`=09l9e{1{5dQV@Sv0rtSV2*)5Iu@C{v;eH2;zEB8$l)Z&x zti|WrM)g#Z@xofY&ehLw`U6foiIZaS{6qcdL;cu8{h5dQ4<70rRsix%fM98Cz>(@X z8Hr6U6k>>@+;de0Mi6)x^~E~vNAaFjB&Clo6!yQ3Qj&kqYpkm{yIiCSfWGh<^cU2} z2=pawcvKurp27+UIIgWXBWz~1u%7@2qmr4&9)n-8Wtxj-qv5Ge&X9zlUI^4xEFXwUs5SjGsAN%0fdq8(T5L;uPA47Sd%o z&c+DD%b%&7G?4r|D!-zwJxJ?FJLtelM~tjk^1rB76gX&s0DS+RYDsInqEQJl=>*65 z9eR6TY(pzxJY44f3Bd(v6$fAHl_0YS{fAd$g#0Pp8i~zqT}N%KZvnTrb+)}m+o${c zVk+w9H|nd1Q}AxIXs$!RyIWo}t{>IP10kq)K_m8e%jJ?0618sMF5gZI-@HBK>C=`p z{6~x0P>KfR%_`q|^l<_z1wE%AmD&xk;Rqt;!EQLqBZwwfjwasQA`X5(>?Oh_4ZGd$H}PN-BatHJm^O@5Rr!41XsL4+nDYG5SUIZ zAj->Iq-=G6KZwfYPA*_myz5MUpGNwufxEly|~GnuHS z+yB+>q)0=AWQl88^3}*frd0k2HSmeO zvVfPPYY9-&TGZjCj=)PDoz|u_*kq$>a~GD;6r6yMH5?-VhpyPzHJU{h-M*>9r_mOF|D@&O1|D~Z{Lg1Ja_WP$Xz zo#hqWCX<(aXp0)3>`Hf_CFul7CkjdvskhJTueMV9iYLdlgisZSsK%ucRmo9+ii$K; zDehFsa}!mc<1$sJ!H6m?YND#C$U3WH_-AmPrK3v?ZZW)Cv?kNET06B^x?4^A)6iwm zP%zD)#rRLABJEF4;mH)V8J-viVXTqKxDR@*M^pk8S}@XN;opL10S`b-0T=*0=!BNb zv}a>Ld=Vpro5W!(gpSS$^E2#Ne}(|VXF7JRZQNyX=X?euXY<0R+NZ_>!bKwg3G^F_ zzm6L01apl71Y`3+l;v8$0NQaa07mbaa2LrD(h$!2t5i@m0YDIA9~)^<3vh%pnm9$- zeGgA307bvV_$PV%2prIOxAOP3`#7e=&_z2)nXM7r>mB=39V6PsBeHpns%DC746ZQ% zAvF7JG|IWN@mf?Q=)*aY2g3;9i{dfO$8AeetoF!(<)%I*iP<88Yew0UF+7 zSJIBDWfWWYadIQT4ps+HcHh_U2^!a{kup9d4L0S{xMviKSiusZXZ)MbfZo^ z5kz@`+7<70t;ChKBGis1LEn(g*yAq(E;kOVc?pE{R66P>7WbFDr_0sP!9tj zhJZSYH=B^Oj|J<2!Gt!GP(Ff8$teR1L7OB@@%ot3KG>hj?}Rnte6nYGgcQN!5l(`# zI8PKCTiSgDTn5LM?&6qgMBl+1yvK$8C6~%OM>O9bQEyG?i)3^^iz_^g1W>-O`#qdd zVjj7V^BwPDyJF4Y{WwEy3UlvR9bSwlfBIqWWjbE7(UKSZ?f@*U{nTTZq}#H6?2;Ee zgOd>TjoyJS4g~a6AMr&vw__eOmyj;n*1$Z9={)p-vFme>ANDZL{Rz5g^oPq1M*Glp z`X~a$G_)lTM?Q#y>9D3c2+ysA`-`TKYSBxKy*Ny4@6 zkZf(o$9had@9@WVcl1v+018Oh1vAAsrG9Mp|81D0%e(r#^jJdoRQiB+SCmPm>%tS) zV4!n3qgrt`#acPZ@V>gdj3j60VRG^q>b*(&qqx1gY##(6P{kVL|!} zJpDf=M{5nZStR&D#j3AP~eC#2@MIk_sQ9CC1~Qu)1}0Wbt9YHE`W zRnt9#>FM8l-LKzQx2|v7me=rS{N=;@t!YjBH-6~-UBt~*TwWoiX{6a2>10rfOiELR zvXr9{%F`%~(KZ^V?X-h-(k|LfduT6B&_3Ev2k0OjqQi8A-k_so(J?wsZ_){xq?0s7 z1uD`souV03v{t|(bnk_z11*QQnsmUbeT>**X%UCO>d&k&^t7O zI!p6(3U!XI&?xE=TA*#H^Ykvwq8_EIbOH4kU85tYx6yTa1NAt)M>^^hy-x<}?eqbq zQ174{lt;ajKBNiMyXYg@k9xP*ZSSFvX%hE)=@(Q)Jwcz)H0piyDNUi?PoL2Y>I1Y$ zCDaG$Ce5KfM4!`X)Q9N{I)nNMeM#p~zd^U?JnEx#n=YcZ=qpO2K1O#agZemqO~NE=`Ni`Jw*@cJ38@Pw+kO?bdSvE8kx@wyNIXzWZ}ue(=?tO zD&VPrr&IJjjpN%Ha%ns2St`>G)FrCWPSkTmvI<|?hf!ao2XqwmC2G(y)Nj!W9Y=ln$rxs{*?9Z5_O;fWFg5YcgZvMMEbAKo z`&Mg?f1{yAtMT>u+MX8~`-;fg3nFK~D@N?AB5z+4qxN-?vfmTi?f1nF`vbAl zz9DwmA7Xw!5_{~A#a{atV#5AJ?6W@=`|Z!f0eev#v~P+-_UGcT{e?JUe<|LuZ;7M! zZDHA8iDUL1aoqk|oUp$UllHe_%C^OfeOJud--(iaPt4i(#cA6SXYB9AS=$xo?6Np- zSHuOI#6??(OLkSfW!J=Idx=(WX+`OJx~AoCt_tb;Eopt+^o6Xt6_L;1UaEW6N{iYJ zVTrZXmh?T#wLIZlt*TXRH!FU<)%2`NOG@FbwwhFL)-1ne`Afp8H+@-edi6@a74_`# zSD!!ems-t|W!(UjSaVla8)C-lH7U77g|!*$Nznqbc-XE#avP%Q=c7(R1du$ST5G4C zpqJY~>Jef!-4y`>r2qjfPgreFkW~eaw<;=iw~=2FctPGf)+1Ne-6ptsT*ohM-)aa~ z5$`t1@}*mEFeg)vGo`w78(zy=m90m0NLQYFthAbsM6)iM6;X=D2?R6Wt8L(iTv~PJ zZUywaJW$L&w+IKcln+vF*+W4Tn80;{yzBe2CVY&4kO4x)^@AL0-^D-%*-ES3^lw&! zEQvUb`IR znU;v5T-}##!GxOiHGFL}L@%h8x4#}im6L6aYj=F zsivp}CcvB^)siSyTNq6yDHBnYg`}#{NHH7n6Gy>fX^s;;l4OQ{;-MOXKikN%Ss?F8w zb>CT(QuO7}{obzO5uIyGGh$hWJtRBrZ>gBmrwNlQNF3t5< z$LbS#5-^9DFh#BL8lrVY^!6ChS3tEQvuMc6O!C`3xo9L1Fk#25y-k_co3 z01T82BsC0jED^{l08AwYNe_c8Bmx-)00SlC#8e%$p zRV)ftf_Rv*Za`-Ws|9^0AJ;umx_u**y3Gk-aF)g%0b4J{-0(C3HGxzg0l<~SAR`K7 z_h9J&ghw&~&>H}`76Xb8=Q_pWW44|RuhFtsaEqm)9+(d71C*0mrb9EvU49sY*mA)3 z4GDy6ol3$6_xVXujH??kPA0)fq5qpnF%E_pF?BXKmjr|(hFdX^SI$RQd#U{xf=u)$ zzT`N{20BhbP0L9C`4w|B0jRHE0msm>rMf)?8|{Jp(bns9Kfb;j>v_vrU)V5O^K7zS ztNbSc@O@H{i4Y{F%_fsz6wyB=#n`g}V>$^2qC;&dDaMWs7*~^EuxV+;FyfLmG}WUa zLVv1fx1Q=5^tu}BdCRH3zJdB~66#Cn-;ZHzL4AIR`cqp|&z5Q}*7KIs?+*KpE$it- z6MPx~-J~GzZU9+GWOvU1;E$7n?B6gCvq|RR9QuEr6ywkaj6^!{JosWg!a_%Q(fbk{!9GQ)s@jobtZeNQ5mfn z70$U9hiPR5q7T~~fqA81)N!KF$8kExrY5~9t5s$f+p4(DDOhd6AsYfJ(ZoeXGsrHv z9>-gO=|5Q&LC$eFd~}>(*IP( z-@+vaV-GUQuPF4`DkD&~T&n=rLReBDy5gW!dHhZCimzAK?DPE%)1cPaARsXDTYu0w zY9Rfov39tty|3Nd^EA~>A*L~8zH5+i2}A!d|FzZ)y}DxL)p4xaY_F7sRFP|)gX^-@ zs#Mz2Q&gAaCG`6ftBugAn6dFnt8g{Y>%)VVMf1PK<%NknQ_o}2#$GXO+=iv$3dqO6 z8J(TIfkO~%xp&L=N{g?xXdJ`+9U~465kK;!Q131z3$Ini4PCH1PX zR(#u9Q_d=6tM_gZk?M%Rd~%vc1o=B|qaBHPY}(`v&=}~;!;`iTKmR@R$HSxxxzBO6Ky7v*_s`aSabDFFU3~&D+1=21Ba* zp+3=lql@8NPAPq2hWg}5&QFJ)wyF8%gS?#YXYq`0v?t^EhILTpX$rZ%J!q3foA1Lm zUC15UjA6l`%~LaK!M*%4-lA*zxd%D<1Gfh~rlRK`px=zHIZRL2q|^gV{xg}-c_Wd| zvqFO7Ol}>6^ndc#V=Vmdr{vEdbC#DC#ts=bla?j+*up)D`)#$m7g%QE6Yd_xe^a6 zoaZX3)ZS44Zd3JyY>}uzDX{ct@7YuZ`q&13ETm7+ARDdIt4)RF83uUs(^UHtHT`jKAysv6j4wOZ6r+ z>~v_hK{|FL3>&h{8GP(?V3!58+G#g zt1A4;63h*opjsU%F^f&L8lr+%w3NKok-m-WWGDpJst{kR3jH$3qZX#vs!v7Y%2-yl zAdAtod6q2k`}p^@&Ay+prU)x=T|c#WKZUTP8Fa`Ei}4RzEDa}bYOI>bd?1QOvQhvtI`nj&QoO%Yg?bq6`G_+4c82asr zjcI1FbF@EwDoNj8Y_8?;EX0c$=!|1JB(s&;srY`<4<)qozU*aQ|(~} z?uxS1i^!C4+M5xO)BFM-AS;YX#qVjZy>Mx;!xoslSMVR)F}qC~M1EZF92iuIAQ zbxQM%76#EZZ5-$OA=5C{&vP&I_hBJaJ}0%<|Ag6L+sID7$Dec+D_#8s z8s9eFfl)dgWWuaDG7QYnfP(xg|I^okv0#wun5 zB$+Bu3LfH-yyJvBMz|kyoQG|QUT*~q@};151q5dpIvU5l>!z;PViCf1 zjXPZ8qK+cSIu5le9G5wc*J$||5-Ip?m5T-!D_jit?K7>U?{|3VG3mLishdV_S1y%H z^9c3-n4+t={x`ukV^x^Kr7R0a4li`idI2i{>kw0nk@e7< z$NAk0g!U$c$kF;12FkP7M(ILxpgws?@dPPrz-z0EG)5SsMG7-iRZw0gQ#eqSO2h1l ziQKWlK>Yvd`4><*2ei%fyu1r;RJ_&GwgbVvhgS!Cq?=mj{A)?yRKF`l9QDrHUQJ;S zt*_e;^njq-4arHzP&JyNB6-L^NG{?kd+@93hgalI?q?h~tgR8!8#yD?(wh+97a^Wo z79pi!eh)3J)WDGe2c6yP(Ed;gI#hc~OI-u?a+!-V7Z14LLEKysD~)9_y`cvZ>fm)W z|DHN{3rtp!ld&<{JA@ai=Z(r&vbQK(TqISw78;K*lv25ArEQ()mh#ugz&{NO>dAOgEXikL7AVa2;iAH6_=6Pc|mXI`avu)zK~!Irl&D67F1%Gix=4Ae@m<=W0Bh z7HSFv_%-C7ntqr#h~|JNk<6 zX-eJ=l#1j5p|5s4l}bZ~YTzpkkus#zc>GzJC>6@SI8QYQ(QEos9nl;nRQ-Yp{Sn?D z|H20&pL479%gm1muAady#*sw`!E$z)Bf9MJ2$?VQ>@G)MYIPWb$|nj81yeyD}*wgPl^AFVG(Z`lFcJrtAnCzUw{KVfYF|tcSXB z6Js~*LXU=um`MyWVhwqJ3iWe;211*r+}HJbycZKZ#<#=tvA_9lPrb3!?9vZHUf@R$ z%gc}!UuWl7*fGeOcMv5@jlnL{a%!K(el<@{!(2%}Rg=|k!7`=&MzvF|!q7pj9**2r zUFqYDTQQ^7L1>@)A{UIPLvpQF!;`#a)?<o&&vT&FrG`{IUDi+XZ{wfF2$U=#Bvwb90GCbSH2)M%_4~EF&A_ zgoixH=A~zm7w}V(Qa~&^W;1Tp({`7whVgGfpb) z7vy+@%*Td~Iv*_O(MFxWRp(l4v(a6(WoZ;de7w5US$VHk9_WUF#U?kgX$p%aEZmm4a z#R)Fh#7T<_HnfsWpJbyXS#wKPrjoUsWc?$RX5cj|c{NEEbII~2Su!NgndH&5N1WcV zdXW-A)E$Mx2onOC7#8@ux>`rwO);OHbxtpb!foDUgm@+-w;JNI2W(d zp1o7+$o^encr?OUbi6};F+7wW-iL?C!;g_Rjc(e=;;KZdI_Dn#h~wk90eLt)u0U~q zym#{$H=MXsC)>jxafBQ57w9m@Dp?!2(AHA^|=3k;? z>3GeV?vPh?$IRMj5FOS>gKc;iu+ASxhxVh7Ll*gC9E%U}qQm@n;4xCn@p~MMkKXsW z;-5pdKy>eTe$=sIEan>ab5lWXK1@e1u-JRQLtz@@oR3G;G>&qIK5mSqb7ucvCc5j@ z{3eA=?4U*bE|bgRO-{W}ab7lPJFzX>IZm91<0OsqsG2zGX_MyUv~$wbd9;m^wx>;U zoF;9We&2uZ%nfrId1%+i*&bT-}l@*K{d^Yr2tL$dz(V%6HG^O9hotS(Q_HRZxAZ zsQT4_+NK88b~U7~P&?F>YFJ&RcFtZ|>Qh&%Yo1A!it1Xm3)g=2I=?WV)Bi)gt~8*o zD{VvD-_jVIPOa=h?)t{y!uHa3^wPI6q;9zAIH}XA=5QwEUol_QKjx(P@9n9k`>26+ zN9oFyA=L9wZ@4tvQ~LKVDLq&kM7vk{{r=#(!?w>1Hb0_nBs|YM`UC1lK(yOJv@?Nd z=N1s{G!UWIy_fWIb?Hh#v>AHn)DSgYr^`+|Hdu{HpI+EljZ0@M-?WWSmC6L}! z8cm+vr|!2kjwR4PkU;;SddR+gP#w3qNp(VUH*JjhX|6j)ep0>7zCD$Uaw^G9tB2)n zQ9U9vc?;(Bw9V~NkK!rk@21k;1gg%QZZ(r{S0&rq84Gh!Jtplv4OkvepzqA{I}%vR z$$E5FCZ4N3>IwVyrqUbF+;nF6%>zRGfwG%npJbaf}2%c zoyGNAiJPjX=G56)nG^LT)lds4d5h5Ag3QyK{PdjbkIXyIXY{mxtK981ck1VqQm$(K zkgFEexo6U)Z&O+YX!*@j{~YVD6#UzSCU=2eZl5ormGcJA>#5RhmX1TUgj#P==hZT< zcc=?$1=l;(s(KRFyHs1P;d-}vO1%@;g97)GT2?FSNwuclIh$io>gUzF)VBlrx2j)I zPpd1Dy9X4r4z6{mbjV5Fmr~EDcR!O-@AeO^r%U$&vcsh#;4Rl%$g&#Tga6cf)O*p- z5kR*ST;^H7Z$AHgR_~QjJ!?lbQ99aF_oS`+KB;@u)_u;_tx4VI1kUeJ--*`m^X~&K z-gf3b^-tCN)dv9W{r-TuaXwu-Cgb}c%lgOA?{BK-)pw!B1OC1KZD$|!AMhWN-x2@l zdcJi0%meBd)px6Zf)*yF=7*%0?@`~2Iw$-S>#4`w(#g`>&YS=Se;+U|hjlEf4>K1q z_xxxSm!YQy<6mQS}M+ zBe=d@>U~&UR3BGAGMkYR*q(G-{iymR%9PZn)TePhBV|9SK0WK&avv8sKA~PvpTYab z)MwS_aD80LeMWuGlv7_;pI295tna{j{pTf0*as9N6 z@T-2MG^2jnpD9;S<7deV#u)JMJwt8};V=J}(F>d=ys4rEV)2U#x_49^0&k zbG|lJ<(X7xE-u-uEcjg|N2He#fN8(b|C9Ue3 zHOD-TQO1U16%ik*2)i1>o!<;F=U!K}Ek;pkbl1Y2ubY+7-?G=q zRujvN`8?3+mC$u{3!oQK3X|9Ab}8_cS8sZIP9B=RpNkvMAl4l7o{XKhUDZ${#3;O4 zy#Zt#9eGUKF*og1Ki2HPq5PVlg`G#-R+busqN1yFG8(~W|AJp#3M(^cGKNC==bKAF zQd^VVnewfgEQ!2Cp?Vd|GjagA1AH`M@N}$LJgHl=y0X9p1WnX20Xp<5P32+W-bgDL zAzI_M;?4LW=GUvvRhnoF?a%nYxgskNB)(tv{U#8vR`UgO78{iibhr?Vd)|o}aAHXZ z{yxIB;w>xzOOR_8Tg}Fb^wuFXfd$wHs;yyOl{d2@q?k15jgs>AS<)*Kz?RUr9@{6- zH~h+Z-_(gQaG}zyFD?Nj;#Ju4EPWPjQ^8`RZbp8#Rd0@s7hj@+Jvrt?gXQX+U!5;6 z_~Bej1yRnRU6eEA808ExMQNZzl(#q)6ldAqt%hJ+AhSbz^@;iAIS#KeQ;sflTu zJN)n|o12(C5*2D7?P^Q;%qd@T+h+Z+OjIaKOSzij(4*|4Tylnzst%#YAFnQchw%%z ziD;+7)Ou<@2d?RGbotpvYo^i&#vIMppHAtkarv8v56ra|`~xek*#q@@JuJ^1s02ZM zwz&ZE2o5OR99Yz?vtTiDbL*QA1iE@)rc#{;n>}#eZ=OHUsLvc&T)~_*-!y*P0Z#Wy zln3PXAPhzb4&h2U`dXwt@D}hu;JpQzm0}2(&pPYQR4S7SUF;zCSvd{;{FzjkZl~6r zBlu0FAn8*WS9&sOj$J@9;3@jM4#_MUdwh7!X*())E!6S(w9d4h?{d#&P|?+#uE;6N z9E`bOhp;urCg2%4~5|6GfSaAp><0~X|QfAOm3m2mKy%1&Z8?X>18ir;GCr#*C{%K zj($DzLQ(S_ zf&m7!)Ksf^OEqH!&1uzHCfIkTbe>5cldG7dnG7%)MN*ZeMkZblS>D}v&~`!~qrM(! z>F^r58)+=Kb8SjgATB4+G!qrd7Eh(UC{qsnFiKaH!YZX93nRC-d7V%Q?`!BJAgn28 z$k7LIEe+m(=#h!?(L;w1PfSf6ng&5vt9}rawwdRL?>~Ox2p(sva~ON)>50>m=4orW zSsE~9r=}0#UzDNjkK28C`q=Rawwr}6vf!8crRYP)CLd%;>I$~@@du9_JH>Jf^H_4* z(eVe59y@vhPjd_NwR)|Ul$|s{EzCColxg$C$q9m#A?260OE;$`4jr*w6|`Sb(w!OD zDHJ|F!Ir_D!HO)rQ*S?RE98Tfg|6}sPuk}>qv1qZy+An4^vNhEF-!}~(Zly+G@LY+ zG4SCTrm}N`8H^|C2w`Uh@W~)Vl_(!n!N*b8PVK~_6Nev}h``YN>iHPhqtmAzo;-YL zdLk->8j2aDeY`*xpt!nOg}6IP@53i1k46PD&1$PzLw{Ja^RXV@hQJroZPM!z%%>EPW-!XZryg+aN&j&uBp&{zmKJ@zU#Q|vuL?AVPFL|D z(`#L7t!O1weVR~97SIVxL4BjPak{1F1Fun^_oY2)iJevbMQR<;bSll2-kQV|98-mg=+TE!WZO3^Z*44BBDMgXW-GQ1n<$hBWRSGYVK((U1z= zU^hsXE7FpYh5I~RsYBbUG`$m3A_CZCJTp}7WOBy66VR9RGK+#mo54_*sZ$&DOd|?| zmu(DcLH~!sRX^`zYr_Iy`h~dFQuff);bX@p$NF_Y5G=}y`a@y^HG(AKWs9~Sg-SUg zPX#n#`%$qT)SFZctA3Q7Sqc3>znRVC?Es=|J;17u_W2b~Ng+73vzA!pFd;jV~(1zcS`A525qu|^{BNka+kG;l-h zVcl^cUO*d$hMYCG?FOUr1QtZl5T0B(*miUc_*`2Vpa5bW;5%%4VH)^8ZRqBt#qi#` z=k}h4DnSLJ@>$@#_7_^`J6PX?)WSmV#M-dP<&oN7SPXj+RF?1(^!B8^Zp_|CB%Bs<)YyK<=Q+kTulNmPRA{_nSS%tl#uCbSmsFe6(ulJQ>@Hw_LFl%E`4v0o_6$1eypL=!cj) zg=8!(n5!S=gGZQ9EAHrkQL(eg{}FG3VI-;k0&tS}S_F0u;979>X*^HVAL=0qb~bS% zeB9t5cssCfw4K(Y!pC7#0gmFCU~eYo!BWHEv8izuHO>NOv!IBXsdyxZ~Du<2r9Zk!gfKSVn!flaQb{|N)=cY$bOaI@X4CNOB;SI6x0yR?P0+{ zGcx~#{|etEC#BILJDDS{8}i9SY0OlV26UIF zp}a-J|AlIXfVPv>7i1Gtuq32QcspGc4Ia5G@T0`4;uriSn62UOYuMPWW$?@5mjg9G zUs`w8@}P!Wz`?m|JmsX;3QlTum|D?%pT4*4whN>!QigKY3QrXtwcNd(f8O~Zw$9I| zE_`ie6s@J(d9>DN zTDz$KvYpw;wfoNIxhZN6w6mSNwi7&o5>K?#@M8_D^jd#&T-q(5-2t=_!St?I^;pK z9B8KVKq~4MC=J33s$px<8?861jU_Am76t$7Ff%r4`#kK?DQfLo*i(fIj*P<`y3bpw z`wd0Q?3?z7ON$NPC|w@@&>eY+h*|QEV4v6pC2LCA62i!=WmoKE#+C=>*8?>e8!AY3 zQ-fP5Ferglcmg|#IaaVV6OWfn98(bYHhP({(0=W8K z)+8nvH95m%SyJ7u1!2dmfn$ljZRbbW8?;>E!HHcqFs)6uu+~uF!4{#3OOes#xjI&Q z#-D{=YMEneag1^U#b^};GIXGEz){eX#n0? zZv@z)u=N|^1cC2LAKU?0(}@r1%HhJe19T7zZYA#4n&wf_VlD7*#)q+#(-c=RUJQyz z2p`~}*SnO`7D4R@XjJdCM`R{^W55^gMhvtBw#Lm?H*nGvT_%<8N$Li!l1NfB919!f z-@qm<^up)83~V#4FoZK@X)&JM(=Y{hgUIlNf2o~Pa;7*M;#+fRfW2?kTJ&!#Wy*gOE z<1%h~c#>f+({xTU-Mp+GRAkv7!U|snS1=rJ#)q}9jy};aOn4mmC}sh>I800oS~n_n zjS4M_EnW7l7#J3+gJiJG3&O(Cl>jGj8JK~1yX-OOwg zLZLD31OI&Nu6oFY{MKM3+l|LzlvDt+)k>1%bRaVne(wrB4&r-}EeV>W%a3hh(yV=I zbPNj&yk`S;2Ovo6ErT3#HyuWzB1el zO_Awf(?q``5G*kj*nK!*fZwfRumWyDI&uiP*<1nFpnn3NFyo2tNHh>kGzJJMEjAJ` zIe`SVDl>6IER9}zc{zD2abJYQd1$8M3jzwFF=-+xfOR)kZdq{x7I)>fX6Q(;Y__uq z0L`Fk$GB2!H5#pD_-+?wS|Dnec$zTu0L)F8V&OMFUIGKr6D%#pld{0s!UjZW4Yesw zdKB#noIxv~4|#3|(!I2@4Bm)=Mqn5r5M)|*6o)G?{LDgRLH!B1CAV`$RH!!Uw1v^I1;Au6jU(F*apFQ{0d#kVp&jcwY#Cw`y0N~3 z*sDm%x{p&G)K@KTVCYo7L^HBlk!UC}iyAThqXQ4Yl|*ja7#X8u-ux}XJP?kW`n&Ds zD%g!}W>ek0d$+OGv7{-7!Hu4=osWu;H#NBiV`Czn4IX2I1)L5Z2YcMQrQKri0^dhp zK>krFj?%lg(1g0c03M7Seq;*FKr}FkFt8)R1w1PlH#UV)DK_SLueT^6lE6dVgtI}B zGqXNq{RD?lVKRdReo`anO9kvC#o@Wh5TmOob`AD{!4t@&?xbZ9 z|MG5n02adn{_Sv$wa{2(I#1<3U36iuaR=N&I_KnEJ{!suk;^!{@MHk?Mc5m&L(X;S zqO;4D-XdolPN(f=Pj8ujTAqpgPk1|LAeooWa>x*iT;iB!l1*BS5S zTB@B6#zWY6l-tgz^!wAW%V$vry*u*qdnh94G<6zLAiy2` z3zcdJ3ma|g!fU8T7*1}uEQDLK6S{TtPKeE6nux4h?uO)HO&Q!~;U{eAC-zB}6dF7s z?CObFu<)LuSOKBx5Se7e#5~Ap1OqKDh5HhYK{m%0Yw8J+S7v9R{GbXIov|s}N9cmF zI&Ru?bs(|akI+qnOIFnRN;9m0WrO+F;*P<0V<0ejB7W-O2sHRg4OM2LH)6+T$u0p; zLxV-I2vs}qBMQ0%y9lm$0b+fb-9xFzV1RRc%ZMt?Qbs1T zzy{6VW~s@i2CT1Ba@1;X95 z!Dxvi3QlVIs}R5Vw>J3HU~FPuy+$7+=h!OQ)bl0|r+hIiA zPQxh;pz9RpDJ#xX;SlRkoS#GcVsicM-kFeKsO%(hns_Ye1e_**Tht!A!sv{Q{L;h- z(Z_U|Il93_9gEVd^+mySgenDruesNl;Ko)kUk5Bm^w#H@P;b-AOfDc98`7(|l&CsV z?3eQOz&MOIp?RG(W|_=Md8&s{bM-tQ34AMjo)z(3N<&PSs2qyk+v}T?&i^fGfsVUW z)~JL-P~_-7reA>`hJrKT3VlF5WwVuzF+#`9}%UjQA^4J~~n zPG_onY5eZPFBn8ZS~4LM#_hJc$S9VEY!&u-d$ExZthk$ym`>U6L5+&zJB?x@`}BCz z4~+{d18YJs__TI$I~a?#c$oM&>d4*b;UVToQ^t%Vktx^77jB3s-v6UojtnT41B4u6;meJ?~{7pa| z{R~Pc)A7m+{XH`H#qPnsig8=>HPkp0^J^8O3Y7{IdK`zI!0Y#l7;))55F1P&)gqWd zG7DQzz~X2ZHoT{M_+Jk;e8Eh}*M$z>;IxP?`|40euq#0u{WL}`!LbDX{G#8DI(i*1 zH_u$&j`Bc)J2~Lavz$EQ4F7oL1Rln3YbNn!)0@Q|QtSVH)RBoHC@|cv7<;8L(86d% zt1EXs<|u+?It7VM=A2y~(e%492e)&oWO8zHFB@k(mq{Y|$wW~o8D3*~jD*>&{=Qw9 zuDN=(Jm&8osbtPJbL7`Lk@|fY`77a_elH5$lT2h@?vsh6Oy*A}65)Gb)1s2?3{!|T zfj_q9u4S5op~JhHvz7^6F!nT5G{l$ad!TfrYEC=z5%&X7tEfysg`r&n5h-iAFeky& zH7Hmq+^0gSS~+-sa~IwtisDmid9>9B^(zHcrm(UD?G-xhK>=()c`AneHG1d22=%EC z>QkZJM{l^OOMOrEQC*U911R$+w#+cgw6hpXLH`@%vzyC9C2Bw=Vu?QeH|;Exx#H6Z z_-2IGq#onMZWEE9pF%#$TOMJQ7zT~$9ZV9fC`vC>7L7sbilY#vFo7RspoSa$U-UreL`ZOML;nD+)wYjryp}NZ`1>k#H60-=xVS za{N-EQNdOM#Wt}X!IKAx0&hm06f_is$U&EZuH!NooaQi^!Km{Tp~1M&Xom4`NS^PK z^3p~kxB3RD@iA}`Lv@0* zJ-37d7Q)4#Op57(PI9qj#BP`#ksK>rTo%=>v5f}x1$aNit5<>b#BVgl5cvi>NuvS> z&m6V23iiQ9KQk7ty+FLZ<|qt3K?sEF(r?aJbX}Y&s!l&1jj_{2MZr98n~CSp{GraC=K&_)Hl7dXb(E< zv}T~7EIWd-9Y9og&|fj6ReXdlLPJvAg3ESUGX}^UHIR6{JZ=%iM+(#5&4k9*QZXT> znavbK;+`kPj3bjO7HA-b(RTpmU+x4*Jv0RGfEk#(1yU0B0b)jm9yNH}oWVK{D>~+( z$~NLZinDw03#O6yDV)Jine+EJ&j=z>8C>PeJ+4`vyT>)hv-h~>dHx>P0?**%+Q)PF zxE6U9AJ=|$B@lQRCm|*bmQ-n7<{z)@SqPS6!iF(b#+DE%_%~9w4Qp~aO$%{3Lyla| zg8!$=IpK*8g1VwUbI=H@9QB!#M$Gn`r{bxN`pt85lY?ay3lVK4v>ERB)=%!BE2wa-F=-z73yj>{OBWyWQ)ISvcB z{t@K$k22Xb`v4m&X~6z0!4~|oVxtG>q}bN8e*}#KKm#;E6`&y`CkEQNsXD0*DbO13&|_ z3Y!*y=nt-0F8>^16+<0FcySZjONj(T2Q8ztL3`p^459%7hoj)46db^md!Dd<8su*3vMpz#g>e%3QnFwo-iZ zM!j~2#}u;;XDE)GRzkycEXBSKZFUg9XC~xCU*BB}1-Y=O555>rL&jO%(=`n|XI(CL z9q5ZIfJ^)sTc2S<48_?8P(II7evFT}#&Mo~k;$3HewAIxDvNT~!`w`XWP*BDnPkaT z=7~phh7*q0Y8ZF238^yG*5b;q$D_jHZc9eRH$7~J>u?yqfPhj!%;)tG*$bHq(`yZG zn?V^y*qPSNm{kOuu;Dbn**(;PvwCF$L#NE-*Z}8-iWLq;7Rxl72q2iN8R_l>Q4V{N#_QMO1R^V z;ZyH}Lwe27F4U4|3Ttj1`uK$hcnXsg{P-}aFoOeOStt{5O|JtF&fNm;JsM^UQ(XvcY$HbNXwfD4;7agURp`LM8_$Iyyq6V@{goZBfv>ItOA zRSpL^sN6Wo&t`T4<*@@G4!V=8!!SEQ0mm^_1n=S;1GLvS1Y=oo)#&|bM1Kzw95sTz zsecMt%-~jHug{$BMr(geq%Z_og!Z?3W7!<>vaG8^{7H?T5fD|b#80FQ#tUdSQWvc> zfHfB3M?Mbr$});QPEK|k6cxmzuJosbfh~bjFWY~js`d2G8I=AGNfYcDgC(e?mel4#B1R2}@|71(ofo2FL(Jo=HD)xU_GonDNrAn-vq?iw3Q{Q0K& zz5a6ZYsR?!%Fik)wg4@}~UNTIByK_di;WHSF?f`Wn=tj1j`a>8A@|-|^M?vB> z%_=86KFVQzFmoC3K0{3z{cENgFZz3tT!LOQLmu9|Jnb0nvs1RLm*qcn>k9wr5XoiO z&w%~9gtRwEcsm?O|2pBs%F7?GFSn9k_{LWf&Tt88`36^$&Aifz%6J(_1#Tfuotf^1 z)&CrW-MpxIv#2w>x>of!P!7oO6&7c{il6*(wouMUzgv+Z-a}&X3d{NpD34Cb;+v=~_e<0sfFrwXe}J`VpCUC!2lDe{uOft!d6 z1!PiixX^~Px~p6Z_@R_)M_$KYQTZmV!Kk zxzN+UNZ3M*D7)D|wQpL_3+~{+;DG*@xP#vuQP)up!L`fq7C*&Dxs&D7hmPTEJtxbP zCnVPw=T20!Yy*G9M{@DQ_yuH5kSK2GgmAb(Bik9Kq2g1Mb@guAvaiLaH$>PcpM}|V zI9b{_kH3N_6>)Jq023a{@&gPw`X_lDq)RiX^W2NpdXiJn&G}Kyb1y!cYCZynl;;N= z+6eT#a6h6;fBSXpfmphVp?$R2g`ybolm|LZsQgAgDOk7 z&OK!<8@b8V>ml6Fcg)tYBao+u=o=Jk^XhIXBnNRl921t$Dp(^kY}0b|^`&=WYF2l{ zeFFK8@DQr;{KinF0n<7R-cT{1+Q0R!Z;b=6vf^?yb`>i3`om2A6_XJr{~Ae@U#`@{ z#kz`$r;i<-nm%#zjHtNIUiARr3O9^K9jgE(>%o)~# zo@S#2QepnSrI5@h3yb z4?%y+z&6Nu6MAYGnNo1|zeA0ly?KI9L~Cj�l(;oOK5Cx|ORSWK5@{j5jk!3=!E+ zFS57)AfgCE9|4NR;)IPjA>9}m66Y(7yTXh1Ev)W9jzMw*tiw zSw_DS1cN%r;;hF!zR>|Bs^bv&Bq*P=Df9~?+@?j{w4eShlx%X%MC-~|sc`X+*DaTz zowiHhRB*o5E`fi^8W`{NH@*;N#W37ra-gW&YcyW`|8||?Wx5wL4Xt3)GOgq3CHkNx zvgKsG3i|g^?lsZP?a87oUb1K}LpU7`r_pNR6E_kZ+a0g76=@a!p_10Sxn{3GTKM3S z$kE01uI2joT&~wbV~=%~>$MZvH*e7rGL%zgI4A{QaL0H14}c2a%N2c9R9LXf>c78h zUBAk86&8vNo(uoH4_9k~Fyd>S--&W6JL5HN^ibg5f0SL&ohguBk+h78+W2U)0(t!h zsF$ojEWKm}=$4}Dz|f0Ck-)tKa^edOSd(-|mNk0GOcv$uL72ff`VWYT;s8PsN3V{I z40mk!pW+${M=T(M@DICJ@s;T4bV5hHqU@Cj=^xqRD=Lv7M2f0cBt*N4i(g78v7rB` zdktSZB|hF+)vtpT|8Z?!acvV~{VG@ZHORciqW`Ns)cVJ0Aab-cm?)v#H6%L+x{4F? z@~)0^%euB;jD*V-CqWg$A?!0(W#--BAUHPT9gpIjY{(UknKZI%Fj(T6!&f2UhQpTs znRfat;(Jsc*8=Jk-VgU3w)`1`D1(YUbpzlM_*Yd0AH$%W?`U+BS{jfyYjq#uNDK^q;WBKV|E= zQX1ozjY-sJz@?At&sg9;vyTjSzMD2FdKhnhhgh-)8OEOQRI)jR%v=sze{TDC;82Ol zRaq|nqY8Boe!*QxzW#tRi1b1IU(iH?m4K)dH$syF-TjCegR{SkfGFx^*f_)cY?cGT zT^t-H{bMN0#o!|8|Aw2*1O5b_{aHd5jM^IRn%+*}7TB8naftjK#xJ-X3B$H%sz+p# z4JDD!HPdzN5i(GKi~PPe%u~Sn^g&wM32|mp&`bh+U!n~T-r)a^iyTDKe~uiFv*Q!U zwDkd5Ig}DU4>HHOY~~`MLBQr`Z?wZmKmwBVfC6j z7;r&zOS$~lUEOY4FH<1VCD|hio8i$LOMZ41L3R?gV6X;eSve!g*|!sIe5sqdH<5BI zS}y<3E(osf9k^|-Tuz40`6VES@e|Xn0U{2G!I39MQpxIXJ>wEG^0!@GZW^=+#F`xI zGY;;bMnC#zm=L`ULVb<7zhd&&Oe6-SGd{^(!xyBxKV?sxEExCFh&6Hf&roDc2gDTq zPT&{ZisbTgLO~WZGKktwpG90JV(OibATa6!j0Z}0aci6%-hx?ML*SUuO6=4>hyJ?! zm1JjfxDQ|6c5&SFUAT{O^N8|A+^@Xs3{=KQr~vXu(v--LvV5s^{DFjLz9sfPKV1>lGaBDe8kzkKze z=W8`Ew}BVZT5UXRutoAqFSI@4V<#|d;(_5Xc+~B(NsOAb<mr(BobSIH)*iRxLsEvfM28staZ5D)0%>$E09p?72i z^hrbm;^+ae%_szKV@^U={+2n9iDn|61O^C6ARk0rKk_AW7=!dM?(oWQb2aM|S4txkyI0pCt{rNcl!*;RAe}{{v z2#E%JVS?6^t~T%uY-o%!jhh#J2yxQ()f{ZUKyfqK=s1fW~7;3U0<7%*r4ke;>fBqhsl5 z90gD71>8(yExP_Qdb?~}#%emt9&${61x3v#4npKgLuFt|1MznJ)>Ikbn)w@^S;A?L zdNU5#q|-hq5%oyDoyjDV(@gkzTluVz zIZS_uw@)%zX7U`8sBaQ8Dib4zv*k##eh*($mdfEtIrt~XxXjVD@8=7NM*App3`x@) zO#T^@7n%GTlka81C?g47Hpgqe!rR|qLMM2a8~wL=OCPKL9VX&b`z_|^bP@ZA{wi~S zz~m2^{1KBsX2NZd=sTLKLWdEGdKIM)-Fw(jq~LQWp>h!w?lOyfkV_W43z(UK)0A$~ z0XK*5JPpukiZ3`Jju%XpyD5q82Mf;OxqLZZj`DytBc8sy1Rb!biIT3AgVvHRpv-96 z#rK}@E|WvsFaM9M9j!{bRmtJ_?ar;<@)_O1@-Ii>EY6*jd;$LzMXE-EAEFQ`8M-*kmm)&xy-NSGhes?`^t2Y!7+fakfRuq z8FGs`yuBV@DoOi4b=--hpW|$vL7t^>O7|axR4qlBXH*o%P>Hh=s Crc$E- diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/posixpath.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/posixpath.cpython-37.pyc deleted file mode 100644 index 68c9f2638b8ad29c075db4abdf209f6dd29fd413..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10472 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 ACIA2c diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/random.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/random.cpython-37.pyc deleted file mode 100644 index 9ad5a3709b0d5af5253b2d8de6b2b6ece2e42ed2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19451 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/re.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/re.cpython-37.pyc deleted file mode 100644 index ac8275259d5aa752d045d9c7f861b7953a85e790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13847 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 G7XAygZvKw| diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/reprlib.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/reprlib.cpython-37.pyc deleted file mode 100644 index 3d2e9550fe2a4e82847382b489e9ca02c792706e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5393 zcmbtYTXP&o74DwE^Xh*=Q=p-35HjESiN1lS=q8=R@}_N+A0XlC8h zvaR(j1tn8wb>{l~e3Rj4{Qkiw ze>%7?eS)wMW7-A(OHr|Y0TFB-yp z%De7OCYpjj#o8UC>xnthddj+u*xO;&^-LHVfLro3~<-`)V!r?{6ikN-|%@ z1GyCVOH{^1oT*49c@|(?`HvE{=BLSKq6$CH{LQ>jevu60qElJ7Fu$^BRn?YpZ%Y=* z!#Je&9xlRG0$w>uktV$uwZ>|!!bD*AeY4Z)^f*ny&%i?f&{LcQdB*yj0C?(+c*()C zIlOrz?&UI4x%5@;Z$=xjA8D@r{#Mo_X3`}VV|;R#xwSe_sz-iia+PV+%ZZX8oF-jx~c27u3Nh9=(?@zZo+mR$JW$; zmz4&v;VXev8Htb%_N&ZDh{_d7(Tk)A%*ra_v|pJU@pk1vvRkP_XJd*{)goDiax2S{ zY_*!-Dq^&>gkh9rd9C+F7zS=-7O|>a=xn5vl(1MPUn6pc$XO!iKmtRO%1Y9sfXjB> zMR%(EUq!7tbqvET42-Ys7$;jTUjN&C`1XHsZTU)lAe}2O5YZhqBa#l66QwIi-I>`s z)1z|oqtR=4ieG}n4E~0}*O2kCt|?4mp@at#4oX{mUU;GbU*o{j%%R5>EisSM6K!z< zWkZ}4ub^y-SH&rmbKU%C=Y#7f_xMuZz#2JSpCQD*KXL!qi%* zLB8R;c#01|1TR@wQ}_qe4FSst!6vAsdu&Y|OT~-3Ib^c=PGmOe6TYN`;0mD#YVx!`Zk8mPsr+4ubdTTyx=mTkG zk2HsV1mpCukI+y!YKO1$5xi(=!l7L(&0XUK8(G4D^RixGL_stVn|YS)81e%J5lvcP z)7Sx%U>W|iG>Bm>Hfv>{`xOtnnsKsFOKrn{5ImJ#4AMkZ)_R^~mAe)d+GrPOXr8zQ zo`s4s#38#zyrWl*1x@>qBdF{_Bvo+~gfC<6dw2?hlEFWD_&4FLP8-AK6p(i+)^lkB zeiZ2m6T+zY6-bTA$Sq-88(c1wu3Qkt$jk1c$2^C~L&Eu#>*zzV-hS#S1b`AT<_0P?Jj6>`|{l15B>^e|DejP9rL%zMw)42{eF&{-_#AJ~jc4oIw)z;#$_w|8HSgy}h=; z_F?|6VYDE3&mj30cMK2KxWGNugdVh*$A_nmxz*G}NDVwZ+8znwu{~->OM(~X3kO0X z6<^xt!9KqXmTq98{31wT9=YEU1+AJ|#kH^c5#~>f^~6*+Lp^qgA5vA#4@I`4{Jfw< z(F8Xi@AG>TR^EIWRvMZW68ujNaMGS}qIH4*p&zN_l#$D5l)PxeYw&eOS_}8CYa=-L zUG$blsh$10p&7JRhI85*FI`$JE(OE+S>v+*@zA&z1ZLMG1muJOExLjvmvo?T}x zjxghRT=lNEv92H)GM%9``S1X`ddBhS(s{U)Cy>XEodEoBeHlveA^quPY($PF2>;1G zA0bUU84hw}TldrLu*ju~MSTN`3I9;lU02{{Po@ct%D4ks!S&vsX`od%(0+n=F_Q0tYx2eK`-_DRA=)`x zPZo<&;L2}fbmp3CfiF_uH6q$W&mFNi`5hXXIbFg=QcB!)@vcIm?Yel2ql&yvW0cm; zVoO!K8A`ws3=}>Hxn_?+Md*Qhw)hzxq(QZt9v*N)v~VgPlFd{;e?>!S`xF$Cjo%pO zfglnVNK2z{0Kq>ioo%io|2&7pWdT8QWF71)AwTrl)155Zr{rT9+E~S?=d9ivdH~5$ zTOf3old}%Yf&+wJ1a>W%J#wFWq;^^s2#((PMZVApn+!0drBa!QeSvcnd_uJ1NyXQX z;yU&lNd~y2|se?TF2K=sc){4gVWZ?nLtjAQ9=sy8RT@| z1i8;(Qt$FFF_9nQQ28^EF(&dO>L8G6{rnQu?tmN*hrCPU2Auxx=!H7E{JXQ+|~*`s$B8dnvvHgkk++On0sUf17Im1K{%OSokTPf-*6Nj{$A74O^Zf{^~7wg^qUr z6VCCWNq!TPgI8)U^xL|AN2jEs)&iZK-k|39iTr@b4~bBsB7aKc77>c{vPVaz0gi|;w`M&_7Dn?-QR}oC=PA# zYi&U0uY2#-Z$9|MV^+>M2lxfnRTgDYxHG-Q9AHlKMe+78cnPw7T_UyUmp7;6A_daKz9T+G$`13xy`td*blH>e0KE!`_ zA#xm_@E6jKqnsH>xyq}#Gp>AlGoE~>W>WHlY9@cl zsqalYLElnAf82HWuhKL5SDm_d*|B*GGlh>9khi}p@28Ty{XKb$GsTYN2cE~&E+3CRHDv4g~iGt~zqf!}$J}eeJXb7}PfHGsZ6 zpq^A8#G41zQ|f7a9}3*X!}z4|8OP_Lg*3v4m)y6##_Nbp;Pc2*);=-UeK`1lIy>*Gm*!GccjkjZ{_T`bBW((4=jKwu2i5swPVnTsqdp=} z7x2`NJo}L6BJxa2>dQzSK(e_j76Y8Vt4z&2R`k2~-lw<0; zdQI&{%7@g))tyLrMwQeRe1DJnq$;bucynCMs=JVKLRFN)_p>TcbND`~=G6kePpRs> z8=OMlUcx*tB7Rc(nN~|*@MccSSiYfZYI)w1T<7M}!D$%}NAOKmR}K4STHeH?cvr2c zRr}_Wyx~Z+3en~n^(oa<`_Q}R1aj5@Ica@97}&im)Dxc=6wIGx-F-o zjn8YuqkeXg9cs)jM)~-`#FiT>FtM;%ZboUojWP_6nq+o5N-sCA22oZo%TwmG)(ssE zUt9?))pG3&YBni-r#FI%i58d3OF_xZM-c5szv71y#*ZQ0thRz^;9_|>NCsZv3dDadBFFIwiwFV->)&R_t zE1S}#51^sYLy&iGJ(OX*>kI`HnmZz;_anLW{tM-57$|>zA*lNnWVshq5H>Mk+$h)= zfxvW#LCe;doElH-dr({-U~n&jC|4?}Mx|8hjN8QSV-7a;6h42QZVsYctKHqrrj{++ zY+%#*Wq+xP{x;_P#!8?~hYtsn^ONz`9>>@K2Yxjy`1q?gntr&pveM8^44b3#L$ecP zXuc_1_PLJAU#YGH<2R31k8xCfZy+OOZ$E^O8L9W47GwzJS`T-Rw2VP4FLOOAjkTJR z&d&yZfQ`C_?!T9gvGNm1$KDg9M12>6vJ%YDdZ4F!gbm`%z^|0+oLO{EBkz0Z*!}3# zsZPfazrP`@*@ zU2O*A=_t(t2=O+`)`I$cb0JF2uFZ7;x4<UHxOw$95^OoUlY>Owr8f{n)`;kahCCU@09b}@vRi5DYc#Ens22cn~Y+bGMJ_p z%{0C0tRBQPrMI)~^kVLYs}DBw%4?_gIIL;);3Ys$_~~Y9v2VM;3Dk&h_v2IK6DQtv z>Q6KW+Kx(H^FI6FRt9lbr4b+A$~FhvnRfOX@&MK{A8{^VNjkAMp)cF|*^|A{XJHMq z2u6m;^@Ta`J3X@kv};gq&=h`(MUYhXF>SMrTD9VH@+Oc_57wm)JD>h~wN@iOsQ_S! zs;hNy8)d=t+yvaCWV8qdezobZG^(Jc0Daq)*1g|*pWc!-O=Kq#YmHucAiQEa(?Rx; zr)MK?eRgVmNETX1SClnekDkP8Mrra|`cX#n7fUZ(JoCbtb5SmAk`)Lv0Y)F;%WO5| z*zn3gNR;Q+lcY3|QC)LSjpy`ZEb%ylCs@pzt4AK-@-S1z8Td&cTQP&jEBJ&YzD};- z4ts+JKD}(Jh^Jw96cAf<518#qn9SnCasrbZhyYfOHJwF)M!-rO$0kEO)dao)ygq>( zX?!xCvz6LPug;Kjs2`B`fFb<~-evL0nfG-_dl#KHw)r)8E7MN5-DY+>-_9)d-9T-S z@40=`t#1kxakBi`Dwa$T*?R+}34)L8Ix;6@ybah9Oy*?G8}-_zfD@i)!F&5x(83jY zbp`N>7~mnUWKtmaO0BYhUJ)c%WBDr3etEVQNHvBnI9si+ZHxo%0K#D97aCxc8lVs$ zeG33c3wl7LQqvSUQPemNREH@SsL*5%^dktOOiciZOQOjf=~GP20i<3!cj~l0hNtoD z4(OQaW0?|Vn3;l9E^+-V%lkJFuXjnYnT;47wn9T_i?exEOZ3>KJzg8BE2X zLvF&LoJ^o~y%FV3Po0~-`11J~MoyiWJ`rV4zcBU6iL)X_%Bq4)24;O{GN;d3F zuKoz#SD1-^-^r)wAA#oEGT?N2cPvJjWjmJ zcTb>tXbqr`{DKEPRQgTtlK|M234$)E?G3l_kc|Vs6@kmzDSiAC&Kz`sD*I-BD_t+j zQ_eiK(<* z>n993mvj%cK2<@M zHJ{_W_5K&hGiY{U07JXX^a$J3OTS3VzBBET;^geTdMHRkb{_W&HwSm# zC2o?Nc3w)8!IcvF0%Lv>+=p0{F4Y?=zk-+{ScvsBmw|M<;T zcH<-J6N&(B=elz(B^w@H%t05!r4xDx97mjhub1&P_Q6c9vLKOhZ>Dhi+J7UTnF%NdcwoCraWDPS^oO6f?dv{Rir@S}LfIgJoc|(0^{~WpswUedK)7 z;Z8f>t;&uPR*%**mahbTXi);%S}o*)TS(wA%2Y!PGDzQ)}7n_JFYt! zwZFh;=ei?F{)o0y_^`5&ifUoRz{-Iw1KJke{j+DR$p#Z#hK;2RE+p{RsI~?<=7iI* z0iMAa0{oS-25>^}HNGQ97g^u&M(PD2Tx4gK82AVPCz8PS^j-vmY=Sh{ z$rLjcq6Pj9;giUee~2ti2Z~KF1#=bGBW8O5^uXUyiY@ zV%yVr1GPl4-G2j0iDqBB(C%-0MM#RIBz043p_e)Ktg zEra|8C^}FB6&&@$(x%Dz?zhVc*_LwjfH3q=fuSD&LqFQiZx6Ny7Kc>oF3gXp;>ffQ zygoptT}li~i4~NtC1JQReowQ+#PN?;nWB0Y#+j*-ZH_fFdryN})rr z&9zP0rQMWL%&E7*fC)MEm)9U>kZ&&6s5{#9t+ibhn1O^=#Fn15~KsHTU1k99(Zkw+y>y=J8Lj=B<3$qUU0btAzL=c2UP-w|B1%p`Yb{No3w(;Q%2~e z;2V$VFu3RmBO{Odk33_Euq9I_`^733qSG%7QL5Rx}_5H z5+k?p7f$-m!ekiCm4TX!isdMIrBIlg2_LFY)Mb?Av2Tp&Y%CJXB#H5#UJGRiN`Ze^ zjE?O3;qh_wGhxZ>j+nAsqz1uvX7cM*C}4mt#z&2~owE?7=kYqq)7=E~9~yQ?_)O80 ze-Ga3XBd#pBC`ZQ3=KC*^`H1ZXvLVQFvKX6Ew8}3qQF5x(I7(ZP)9g{Qq)=wV4o4c zk!YZ2`DXUs4&w+LrWZ^{1ow$%U?ztRK){;GL6&3$`hVDc;52lF9V;>LlR&s7_I)3@ zC7M*7g9SJ57QL)T<-s80#@Of?bwV04bZXf3VA4T8G3<<_24RTwAxA$Xc}Khv_dz#{ zk_l_d`6BOq5})uqn%aaMZTPOw4sLl(k4z}_`O1lnef5XH6Qqo0pXx~?akpu5%-nzy zM|iQ6)#QJzodT2lYg=h(x^Ti)b&Hw#*0)_vYplcd2_U#-p=1} z^cR~c7$dSdR0Vic`15#GZqbyrLY{rkW*5oRE!29m9k(l`4sVNUopu!xFO<@NI!stVhvc$+Q7is<1o< za9gVr;G&FPMt;ccQasl%TP`Zt_Da=elmkK1P^m^4MmD4T+*(asmUIhE?gY~|(wYR* zClPS~YDR3QzP|u)qt1U2F**X|0j7iQr~op-ci7!8pgHVn){;0rP!b^Y3tax?PPj|~ zE&&fTe|NzpIc37-$H1wAi1H*?Sb2-YA>^$HSo!GQONUpCRTDoa`=2ZEt11$ z#Kx2Z=kK-wSCANTn-ho?EY#-PdHrQP_uJ>bWkTv6bh(`9eQdXImbtVb!t_`+IsQS3l~JQs*f`%f39@l)VZm%uNpTK zD!il2oO}(%8;{!#9o4V1Hc~2BdTWg^(6qOX_eYs#V+F6J+3#bX?`QA>46ZPEgTXZh z>`Iht=qfl{w1WviIiGJNxR0?MYskW@CK326sb4am{jQ`1OxB@^sfiG72bqSqdpAPYHBI35748VDNP9D z`aJdf5ZFEaq}a$P)Kkz*Q7A{8=Hdqd5?O5CS^^L-6QdM1qTRHx4$$Ktr2y10>=v*! z>HiX!{PMRi+4?-naI3-yy*bY#{yvm87_7JH0Z5 zMmEf_%5-fQQ|?$-x&FmnHvp*y34>wHx{N_ICC-UBKF?S2iTh;sbZeOpGd4iD6 zF~O+K=kaX$YgnpoL0bhisJ?C|YC|Tp?2VP)zy?C(n(*x-bzUZedfK=wufshQq6*wA z4LK2hGcIMsR?D4(m0bW~gDy?PJ#t7!qDeSW|1cTM38{i?Dw?$vk4~Dj;_*FM(^&ix zF1H$6GmKqP1!V6)zn)GiVi7hPw`4eb$Zfq0ZKW*wJoFlUrB~n6tY2!0JHndEesc}> zlO7=m^m#JQL#;2R>z_$2tDSo*Tb(A3 z`CVcNs#6`eb*EtvIvPFOm#Lmsm{(e%st*1d-FErgw-a@>^IbANqtUJsW*!(bk&;5P zHFW7JL#B%|vzze0Fziu&E>uB{+a&yVAc{saR-vDX>xn3u`ZZ{a;$uWrJZ zRcJ(SxY+jIR7BsPj(rB&;*}^{t~K#3Dtfs4(@wntt*uPa=TP|$x&l|n*pO2|M~vn+ zHR|erfV{V+3k1wI@VayfdTppyr=ibA8fXA~ENGrHo`&=;kX-0AjdRz)%-C`{dN`t7 zm-pi4uq_Kcxv(@p4yr*viFXY?l$wlJ<4+=Izfc!=rUC2IUlL^yhi4;kZGGDI4o~_I zK?O|jeiQ9UPv<=2G1&yZhZ5HVMa#SeccbPodx`R+ZF*?JzpcAgE4&z-`!JN;-8h%$ zD}Xgb(*~pmA|9U^fqy!*2R!*flR4D`^iROvw|2g;x(p{X9cv<9u2(nwvE{2{Pzs3O z_f2Lh9wkZYKV)3myQKeKrDoR)gV&Ohtfri(0f7y>jF?6bV^j?>R^tf81+xkx2r+F^ zlkvCcZb=jnJ2kf!$wJ_{eHVL_yrC#2FjJ!b?X*X=nQttwQYShlURm(;fRclhf$A_g zsz7Z8*Ff-rPqIVTofpR8vCNs9ddRc)>_DozB~C$3ve+eTm}gN{{M;PLY2N)fIba6;psJtWK=t zA}ca4zPkW0X^J}UD`wih8=ce+@_my&N=EwK>!eO#69RTQBE28QK&gbh}>4 zhag1!)}th%kl1m206G!s$Z%k~>4GdiX~-h1e6A%-u=v4}`XU_qy}PIdK}mSMjv2QW zLhyW5O~gKI)(MW-Y;x)y&M?N4!dI04aA1znAc3MX0f;889jl8Ya6DCqIzPgJjv%K4 z*^-JN4wU-LysLi_sedbjt@~@;qXn+kfH49hQ3Q@ds)vxcqixUrcuN+loeq%)%oQx(crrP@AvvG} z12a^-4xRBQQ_X?v=)))BsqqQ-6W%9MICP97@9@`v@cp(M?r-d1tm|`gPy?RxgtKnhsP%8Ib~y$ zvn@^_20J#1NgTJ67h@sTW;@1Z6Z|7Rp3*;#y`p~#LFCQ1AP;gWa1gC^H1alDt&_7j z_#?jQV*cwask9X@Fgs;i`Sl>fbtZiyu-awl79j<(e=Y!-RN2g25 zVRnHM)CJHKNo_axGkqMdLsrJ_8NCk7Tyn01^pxD|DM>qg9YRLQyABbegqR^L=_mzM z8D(HRgLNnci~_e%#-a1fp+)Na;p_7=9DYWYHp<9a>z_kXhqT~~F_bkWlqc%_Jh76Y zF?oofH2*Mc-CvT^+o*RIo1~)y=q}qzueTovVZWF|1LM1*q0-FR7oIKQK*9NQ7p702 zf{o$XnWJ6LL#4AbFP-R0D7?a>0;j3v(H~^TIS{UDhYyKz*oGXYFdb3a_`Y#OM4Cb# zjLJ0y{{l@heS9eDOF+~38Hx!6$KDMdh;m@7W}#_C-Fma6aY+0ZSl2&B0JB?Tejct< zL+A;PESM4i3jIrbTZ~gm0Nki(7g@ZiqW<^^9oGMZxl^b^Cf=@#v|!qjH4y?a&@(I6fPns|1eEwR3t(p3`j{4-BVpkiY|!9*36fA~c`53GsTm4(bjWh5V!T|}SJ+(DpYL;*i){X(X%b|^% zYyR!-npc1OlCv@0E~1XJx2r?y970d1bfv%4j=oANXUO*UZFhAqyt97e5>#W#Gq%xo z7W=rb_2q;>0XuzrQe-h~7a8h8%1P;Ohm^-Ak!=hzNf+`IT*(a;JJMKW8dqo}D?xNq zKyyg$MRWHjIM0Y5pk>&3M0@fq@AKL?x|$>Nt8 zTSgG&W~wV^fDfYL%nRpBr%sI82l!JsEGcQm{U;AzhRQsnlq|CVjyWOj|ks~QD2-jG>-i~ zE0UmlPuns64EOYL6&qv>Ty&cERLp8g%wp}&Rz z+~=?1YpQhzblnMilTd2=T4-Twn2gFH>JrNO5%wG8p@n!Wk2w_xj8e!Em-#a4ZS4}; z*;{Cqh2mUaVXncAR&SOKW~tzn{E_6P@HvT(oHI3+AZXd#8}M$0I0DkQ?U98OBA06Y zNDQYPN4pLIHdGld@Zby#swL2omjW4#Z(Xs>!fE>UKyx6zQ`Y-U$L>gB?7R!UDOS@T z=DJRR{R%5kcv8nUE*mAG-y8@r>O~G_KZ1F5`nA!I;S|9ZopU|q+~v%9KjN*XNv}ml zFt|Szd6SPCK?u^Wxk$jkijQilb|8;n%kOAf??O|5#5P6p$dKkh>>?{w zfre84IBtGqA!!iBXenD3>8cFL5}Z6tC!i{A*Q!O~8G-}8={Xpg!YA-X{4+Kt+a9p& zgIj4>=yB51yw@{0g#l}_N`np@LtZhItscWsbj)fyHJ765_n47Jv*k5FmAR`SfZrha zWIH{UX|wAu_zlZTW>Mm?2c%p)GuhDz**uBEnDEmUr3wI$B_?AoSPy)xxvB#GP*DGM z7;JC@x{Q^==`;bV1jMYq$AXt|pAbT58M01+G5TJ?4K8R2Zga8z3>l1TS=>2;nY%zV z79Qe$7y*J14EcmZH%o3j_~M4*Z6KqwuAH|3GblV`yO(Kqs&x;^&jZj(nOh<-P)Zqb z?^^eDO+q~gl=L4RDMNE=yyaz6v>xutXSXN^9e~3=jIj$dHDMU_aa_%ij~j^krZ-nC zv-mcE5C(G2qgd^u6fn2`eWXIgBsvE;rI;(4qC%&=sK0CW;KyPR#LgW-O~n7C1!9B37nTRl(f{{GA{LVmNM9*%;JvQO)upF!qLJcTJDX5w)GI>_+x1u!=ReRmh_8 zZx|m|C3V82fI5jUDW;3K{Y*PA-v_~lKwO6~50(jfDxNQewE{Rb6F!47I20}HnK)wW zv&fOfX@U$&r@jCoA1a|-+r0}SK2$(+R^segj*BZDF>KIjf)NmW8?@rN0I?u%PnCpa8&k-!TW`J6xc!nZ0)5Gw#+9 z*djS-1=jK}?RdT=<0%++Px=pbON9F&%w~W24$M`|J9X`P&@)`OgPVFl!YDJ6M#bWG zA_W}cuDl5suxPTgCw$!Pv__1A+r0!!JR(>6;3TT-6aZ0Br=a?@f5^N~D(%HUPtnLt z-f9dzqCATp@k?m#n6XgRwn^=QvzN*D(v5D>!glql^6lDuk0Z=B2Bp*#Lcj z;7;9&2)Mmk2=u+9F^Q+T(=lU}M>C@Ov?!F-PzPh|@9alc72Tr%QCx;h4h_y6>{^&t zDs9NdaIK8pJ#LD}e64@E9U*(xnK0422vDHJA#*I&s%~UjVti|DH*vL_y$o~@K}psg z9g4y37Fr&nH=!hQMOHG8;66I4f*u!J=?_X6u)U4$CPvI775Gfdb4Ja=!7KniE#Yum zcdyl#>gZKWy(~lt!!C^eJ49sqcNrv-aO;kwR^B4Uok9lRUM3J_K{G1r&_SqRc5U9+ zheh9w>nbpD`rorMB4p8!>VJmV_^@HZMbgj5%d(RvPdXsnIsK=u1|_tlFQSU5-)si) zaKw#6!0}NEL?cRpwCW#ZbAA%s#~9IRAJOa+h&UtEDH~?nSmEI>3r{8@_fat8Fe^}) z21`ys+UD%szr|TXReuu`>|D zsq-gJemG`l^&hb2|AGL_^*0&!lRy@l#QHd!5;=_%x6)*3GnGe-#CTOzYv33qfTmgs&3NHKv2-B+Mmd_L2fsM5=^GM zbsu;xa+UV@Qdf3t27l~!{ok4XKM>69j&CcW-Yb5ctU8W#LmSqYyoyrG;rx#EiS8&>IPiG&jrlnIFjs63 zns8ESmzp#fbGu+yI^;a21|o?V=!kJSBoVHCQcOrESb~6OQ!I57PTUkTB!hluO`Hga z;EeO(MD5n;t|L#0i$uc4iJf=JOI9YbvlNQ~AmZKV z>hH2p)QhTamWe=S38Au~tmL8plnKe!(SO88KM4d^-GRr~2>F7mb`jo-9fvNG8RAO; z^De2v1^)0_4_y$q55pMn7Sx!Ui$zQLKC5KF4V$j%*{vlIZo81ZU}H{4s^KG&P5Tcb zLMynr1IId&$+6mS4A>KL0=aZC6??7sovw#G*dwsZuHf_;ye8;j^21{| z#72{7!Y~k`0xa{9+CNP05ymCeXG{XlAbbIVh0qi^VZ;Bfb0kFZjvQ~%?;@6*WFh)b zbl|^*2de{z_+-wrga?{%PHsB}eIpfd2ve!nk8XUr4bh4UtJl6?PO4;}InQioRT}#7 z#}(or1Q%8xZ{`;B@Thm^aIOIMP`v%3_Zeu{+u3jhZ~JjJncDKqcF~kXt*~{RFZ zSW~K48nENP#`-CVv~o1DVltQkVO}0FDXq+8lV9dN47+&0(MohOTsbldvT{!$vhjGr z43U6^8P+5OB3q`9 zu!Z&xt6{l^E+D^!wk8(njTWQ_uf-aNZbdIZ2l%2xczF7mX9Gx-Y*m5|(UQR&_OScy z{U+9N2RlXVgy68*E{BOLW`Pq%F3}7K*Z3W@Li8I!m#uo}y=aBx5J69`Wn2~=#+?wZ z5S^9r$H)XE*z)q!q{!tnRj5~Dw%Gc@tjkI6L_(p+A>=(N95a7)FrjFnPW2b2X08E$ z8mONAj*Xwm@p%Owe^afyU$&YF)8CktIRsaWL;4*+zfl?QkF&+&F>~!pzW92>KSp-k zd?J_gn*F-X3aEK7&IM^ztu$q~2_=K?yKG{?Xw*sQ|IOe}7+hrFCjnUweJ6sibNh}V z;tWwsfFq2c9Y%k!2eG|Cad{v%`s?#H*K+gf91ba{Y6!U}EYHLACSR?gW&@bjsD$R= z&)OQDmIQPjr_-UslCuo0-7nK7uru)tZ;9wlOt2p@A2Hxbe8lERv>~hv{1g{~I2Kc* zFxuc76iMRX+Ty#Z`hb3Mh85=+cv&lBbGUE>H~cdV z9`{SQCkHWB2DY;<-3HqkF3D7Ye-$S6Sxh(-Qp|*ddsy5k%>nELq5>NGQv#9DfUNOc z9dU8*UNc!ku3xf-1h#k$JGz;@K=IH!;7*`qm45gC-zr%n7V#-0PC3T(x429xJ&H-2 z8KAdlGVOX8Y4O!YBZ%u=40u7&t)@JO`82{omS&uU+H$+_Bin^stfjVlExp5eTm^qc z-bll%m_R2DHJ((dtrTwR;mKhhU3|qTdyvPNTV8?EhqnrWPD^P+Jrzo&rIgnMw~vdq zc_J4lmEl7}8vkjO${53qP}e*UGjc1^qsCCs)~}qTt``Od-bP7Kr_mt3kJ1nVsPceFM*V}WJ=Rm-6Zhi?h=^%Lj(DIia7laTukhCz!7VD`8m#xs3!gjOzunp$ zr%4%;2&^xd{cS9oUSaSh1X2H4x%RQkr7Q)VxN#E`IrA>$vU^r`s5Wk28J;cEQMM#a z>;xee8X*V?>d(RZ%1gUxAbVc7U{F3iIpX+Fd+(e_iFfuQ=-JiW^a5(XjR>zrrehKH zjn*}Le;Qgtn#IAkO&Ych8b<4$o#Y3@MwSeAyYBq)?_YUavBeGs`6V}80Vv~Je*=fD z;i+yMdT)quiyFuz_BGSZ0xn!G=&x8-(Y2?eQi)?YYxw1MYOx4^cUvEx24MbYUZl-| zu>`e9ms7xQ&)Exjh(@j5$;W+U^6M!uQQ^me)-8!R14xjISS;u^*Wm+;YbnLl2Jj<{ z;v=eVn7A(y{9%qqqXT zGtRa!x?4LE8|xxd@MNtD7z2U=_ymed48;H`IJP4VU*b6&+Y{~~(+T7uM`o*!=@nAh zfVF4!?4{1+U_aHddCY#|dC?M%bSqHUQi(l=9UV6>7^@d-_tpBqF-!)_Yq-t_H&NM1n@%7hc9*!Bb0NgSA%SPa z;(Fwlfef~bauzH^f}F_+WWWvWPEsghB3`2*aILrTWRTh2jBW5GeiSHPce%|kz;)e& zC*oVi4SIW&83%gWj&hYoZEcyqUxeE{f)JMj=HuDa2if!k2;dWhjky!avGMm2$sI(* z8ReDSxTJ%YFn;s)7@YVY#kV-E@#a2mA6)0~86>bK^jU0*F1b=w%27FR&xpZ?# z?vKPz@x7Vny&u;=!}af7cjobf1gn20@9-0S@w=@|J!{@IhjHs*cH?8>t7-Ns!Tbbi43ixj+9F;mDr(JoxXB?+q& zml*OVT*#6S%B{4|fx^P1D+mP`3=Rx9?`#Nm**||``gwcF^aPM%axX2pbHhK!yON@m zY#?rMvjydbTiD#0!ith}3_LrCL~Lt8aYCr29*UH9>s(>!D@1<0D@tm{4mndg_hG-y zy>b~b+>>pTz}>mn8h8g3k}9#iklXGNVz!<=J zrUiq_fjKC!P9RNxoPnPN_aPPyluSlr2V3G!V;3CUv(efwB2C8>+LLuEN^|7EC>Ki- z$$*4DcGMu298*qTo;DtP*n9HF@sY2644=?P0AIzuTkdsd+qpr3(B=0H_Z94-RWEi| z@_;lN>zGhcae2nH`)4Q&@4-}M*~&5;%e#HY=7V~$v7(>(QI5k*XKU|{Q6!lXCMcfw z-Ka#|tHkIGrh>TPPRE#;I}?ZL6#KI21X&_GtL%iPary7Z&BM5S*Ush>pGtdUSeH5B zUQ~qx6;LSyW7csqi`HYTojfIu1q5@18vU2@#3+x%3u4a4w@QeI1N@8Y;2WE8La1-b zJ!JZQ?Aos|m_;z&Z+a~NA%fyKnwjCns|(Pe;8Gau96D(RK^;FORMj&%{?d>{kb`eK z9>y@|$P~!v_o4QWbM((5;tb?-RAz%Kg&HEh{%gc5W{^VlH~7@S)Sk>9aIT~2EIf`W zdGZD(q$4)$qV5OSU+>Hm6eB-{sKA#5Q&afGx~@lD9U$N~o|`fX(j-^>!b1suTzxl& zJN}9uV}-(ia~91{l>~^djs(&iQ{B(lAcG+W_cQo01_v2n79I0LJ=`;L z7qz+U{3CqKF`!CTlg7yx< zP((1Zr+l?hRml}yB`8E-*$d5STas5f^l8MHFY)o~41R~f?=zqiucne+b7zUuiymd{ z&l%jofYv@^je#(U+m{)LR-5W)QEur5vP1P;T<$2sd-p z^4a2(`M!KHUv%8U@xmj+DISEvdu$eb+b~}!+>uWq#}oPf{0P49$fxt!{8)a7H|#M# eb9Tafu5g&vCvz+r8p9$zjPUH``wRCL9{GPN5d22~ diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/site.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/site.cpython-37.pyc deleted file mode 100644 index 79d61d6591879d7a30ab45c4dac301a674507814..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21822 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 E0I#uSCjbBd diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_compile.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_compile.cpython-37.pyc deleted file mode 100644 index 64848b90ec855998b4bb087065e0f018783cc15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15246 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_constants.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_constants.cpython-37.pyc deleted file mode 100644 index 4efd9a7c32a1759e568dcb7dfa4d1ebd06a28ad0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6334 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 Cz;qM< diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_parse.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/sre_parse.cpython-37.pyc deleted file mode 100644 index 7aa414cc548ceea7aee4f78ed5fce8aa70014e8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21329 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/stat.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/stat.cpython-37.pyc deleted file mode 100644 index 5acce5c08f333d5f381e5914df984c21fd78a1d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4387 zcmb7H&3DsC5|~Z&lWH`I?mh+^zJ3j z+9F1wh!HJeG!2YI86)@;dT;IwfeZ@`%a)d;=6Fov_Ga>LikOupdRL^TvMhmaNvRj_ z-JIL>{94oZGHct-y6>QWnm!jT!F{K>t_tpLH+)ZZ*HqU_qrE?sQfo~hsS%0k zWYXGRU+13BLEZLh>->qjCfqHR)T*=9a)qx>C-*3w_hcfN#?oFNkr@D=j9`31-nT?^HB(Kf=Yh~vnAKDwU) z^sG0a`bJIE>bPK3uf^+5t)T*cn+H)XmU>PhstX;UXdxeY z3U7P`6s8#WKcS%@6f7h6B{*S_NdKY(&!uiWwDE_VKAjUFha3L2-Z;Q@MY<5~T)pNe zZy08&W9Z9A8G5?s&`p)&Ht&b0&=C-n4bwI|5L`J5g2|o;)VCXs&)sdm_weDKxU^uu z>KI)`-jVQZbtH_nL&xnNox6L#pki;9w7-$~m_(Hb?(b-aHb@jAF(P9`R4I@fzsoa$ zyc)<5$n`*O1+oa_w}I>hvK7eh0@)8_`&07K6@b2QvdhS+>|Y#Qv87JVh_~;e-(*@$A*KL(2}Y}QYSQJP>ep5qJc!p? zEj;3b*w3!hO!bEcCyTYX*kb*m1?yXNd={gVqWeHi?DzF|?B1h@N=i&l$|Ld+(zr4r z3ko=1N95^JsuB!TtKinFRW@MRRk}2=I5K+42+O?oiX~7kE$XG0VNFHPhvht$)Wp)6 z7Mf&jy%=%DPh5_;@ahqstb*W(6GToC87Fd<$ax|ckziN2%4sP@9HlglgLRl);V~=d z7!!0<2-=$kZG(cg9YJed(5e%Z_(DYzHnj+In4uBqs#d})M^y95UJe;k%jUxomrUK( z!YXZ9%SF1S#Gt0yrs}!mw zBVQ?&*$}dNu~@OQbBkK2$d=1mDIc;%Ir~#ZV}qf2C7POH6mmwfY-*OJMP>_nKChM7 zpjD`5&D?_i3hReZ=;)VJQNLtWGTNPyV3o3EYr(L^1BxZ33>z=#i&`~n+onEOv5|{< zW#_u;J8+!tQei&nIgOp|uGUR0XB+0qA&pkbnJZ-*p?7!HcJE48S9;0T=5Y>Js+NtD zT0GRQWSGV5BAe)HS2Ao2AT};h_UCc(^X%dwo2r#FD|6L+*3KRZhfyftD$&@Pu2z&< zMrm>7PCX1 nJKR@P^SM#N9^>-^uxlk_Hxu@J?=VG~N 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 D_?!$| diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/tempfile.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/tempfile.cpython-37.pyc deleted file mode 100644 index 17067f2ecf1def3b0a512927894d06090c71d051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22275 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/token.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/token.cpython-37.pyc deleted file mode 100644 index 3550481402af3dfcb2bfb7f6c1960a7f15de034d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3642 zcmcguOH&(360UBwUac4Ajg7}L7#m@O{C*972-E_NMa!0C^D zVdgdwBCV3n#@ry9UC*U%lge&|KO!Fy7@XIj6ufSD44cB-AX88=v z@vD&J*Wfyzg&TYhZt^7D;@9CezX5mnO}NW%!99K(?(;kFfZv6O{2qMG@54NQ0FU@X zc+9_sCwv~B@<)(@h3}d1_<(hu9I`Y!koZ$W>ZFXPorOboC`k+!LH?fcMM#4O+capP zV5>m}maxqjOR&5pf0E3CkvU+eEOZ)+>TG!G(5L4 zk(d(!?3WvrZ9}NpVo58kWc5@|M6yLaub+_KY*EW+j%f3aaKG4*OyD7)jXd%a_z3(2 z0fHa_CBRXLAWRS;z*JyIF@ipVGX(tv0|bKvLj=PFBLt%aV+3aj&Jm0goG18--~vIM z;3B~U!6d;Yf+>Q_1Xl>A2@(V|1Xl^J5zG?I5hMw&6Wk!UNpOqcHo+Z&y9DaW_rd`dG6!a9WYhk{^u5hh)9>Hrd*< zH=2!GbN7NLV%w}7R{L<02 zpk6BHGnt}RB0qOso4b%jUXxZ9@w2GIq~DS1?MXGCA#*}9bJ+Y^BJIR0{Qj6k`NU35 zPp_m3&$PmC$R+Rp^o3mPx(}r;<-hCyztIgWajeeT-BxN#j$>jf(? zoMoLb_#L(xIh5N0mqK)@V2!m^loi@F9e}v?e*K6PssFtQ~s)*$MVm_Bnm#XD0+~D~N3$tw(uhoHNKB8eq3v5$W=LlHZT6GRN->ID^j65ArV+5Fe<#%16)<1*}KiXVKP5eK=B`MS9R^k)z1CKWrA&Vv0|wo$F`fYB=)8~foL z)|2BZvLDSR^Krv8o94s#l%)zu-G4j@#=Ba>_%{B=UUOk)`rFhjzdrk5t=E>l_cnzSpmM*LmV+^*R1?TWc&n3hR(Zr?v;#UI6|U|*R; z&xG{Rq{A>VDr6HYxV2{q1*Lrup1RQxO0$LN&lfcch45K6Gaa}yl6>vLwMKC=1$9`x`X1Hrfq;wwhUBD!ZG5) zTWf%^E7VtXUi9=O;#E4nI)g~2S*H(+GwMGW@>3CD%AvExq5c0d0@VG+j zxO3LT5}euainPcn9JNDqXT8vnsQlBEDL|R49#k} zOr1)-UM`y}#G~k`6;1f`mn#ceLHLTLLRMcAeqCG5Wp$j$>S;|c313=sTP62ARS-(S z#a!{l0`>{Li}_q$r)Fg(C6uDJk`>DH+{>cy;)M3n?x*uF7f=jY8YJU;I?#ij4w~wA zRo9blKio63H{-h1TR@I>yRlRK-GS(d5j}=eOL_yR=5z-_y#Y6deP0mWX*q=v!x*~p z^A%EsLVi^Qv|KLxyqGNtIsaU!8V(jp`DdCg{IpjTTv^W{o4%M&u1H_@t;Dl>;7pmB4~3{TI8ci2DEl diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/tokenize.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/tokenize.cpython-37.pyc deleted file mode 100644 index b2785dd80479047374b2bf90d71c2e16eb53b8a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17874 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/types.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/types.cpython-37.pyc deleted file mode 100644 index 67f45e22c119bd77813d9945d99c9c44061c3a73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9019 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 YP)wcXRgFr;JXx{K`P#MG1@qef0rhKs^Z)<= diff --git a/experiment/simulation/backend/venv/lib/python3.7/__pycache__/warnings.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/__pycache__/warnings.cpython-37.pyc deleted file mode 100644 index a988d4dda3d6b5f801454aa4ff631834c26bcbf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13879 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 i2FKCZxl^TS#1D)dxVv5=hRpQ2* len(other): - return False - for elem in self: - if elem not in other: - return False - return True - - def __lt__(self, other): - if not isinstance(other, Set): - return NotImplemented - return len(self) < len(other) and self.__le__(other) - - def __gt__(self, other): - if not isinstance(other, Set): - return NotImplemented - return len(self) > len(other) and self.__ge__(other) - - def __ge__(self, other): - if not isinstance(other, Set): - return NotImplemented - if len(self) < len(other): - return False - for elem in other: - if elem not in self: - return False - return True - - def __eq__(self, other): - if not isinstance(other, Set): - return NotImplemented - return len(self) == len(other) and self.__le__(other) - - @classmethod - def _from_iterable(cls, it): - '''Construct an instance of the class from any iterable input. - - Must override this method if the class constructor signature - does not accept an iterable for an input. - ''' - return cls(it) - - def __and__(self, other): - if not isinstance(other, Iterable): - return NotImplemented - return self._from_iterable(value for value in other if value in self) - - __rand__ = __and__ - - def isdisjoint(self, other): - 'Return True if two sets have a null intersection.' - for value in other: - if value in self: - return False - return True - - def __or__(self, other): - if not isinstance(other, Iterable): - return NotImplemented - chain = (e for s in (self, other) for e in s) - return self._from_iterable(chain) - - __ror__ = __or__ - - def __sub__(self, other): - if not isinstance(other, Set): - if not isinstance(other, Iterable): - return NotImplemented - other = self._from_iterable(other) - return self._from_iterable(value for value in self - if value not in other) - - def __rsub__(self, other): - if not isinstance(other, Set): - if not isinstance(other, Iterable): - return NotImplemented - other = self._from_iterable(other) - return self._from_iterable(value for value in other - if value not in self) - - def __xor__(self, other): - if not isinstance(other, Set): - if not isinstance(other, Iterable): - return NotImplemented - other = self._from_iterable(other) - return (self - other) | (other - self) - - __rxor__ = __xor__ - - def _hash(self): - """Compute the hash value of a set. - - Note that we don't define __hash__: not all sets are hashable. - But if you define a hashable set type, its __hash__ should - call this function. - - This must be compatible __eq__. - - All sets ought to compare equal if they contain the same - elements, regardless of how they are implemented, and - regardless of the order of the elements; so there's not much - freedom for __eq__ or __hash__. We match the algorithm used - by the built-in frozenset type. - """ - MAX = sys.maxsize - MASK = 2 * MAX + 1 - n = len(self) - h = 1927868237 * (n + 1) - h &= MASK - for x in self: - hx = hash(x) - h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 - h &= MASK - h = h * 69069 + 907133923 - h &= MASK - if h > MAX: - h -= MASK + 1 - if h == -1: - h = 590923713 - return h - -Set.register(frozenset) - - -class MutableSet(Set): - """A mutable set is a finite, iterable container. - - This class provides concrete generic implementations of all - methods except for __contains__, __iter__, __len__, - add(), and discard(). - - To override the comparisons (presumably for speed, as the - semantics are fixed), all you have to do is redefine __le__ and - then the other operations will automatically follow suit. - """ - - __slots__ = () - - @abstractmethod - def add(self, value): - """Add an element.""" - raise NotImplementedError - - @abstractmethod - def discard(self, value): - """Remove an element. Do not raise an exception if absent.""" - raise NotImplementedError - - def remove(self, value): - """Remove an element. If not a member, raise a KeyError.""" - if value not in self: - raise KeyError(value) - self.discard(value) - - def pop(self): - """Return the popped value. Raise KeyError if empty.""" - it = iter(self) - try: - value = next(it) - except StopIteration: - raise KeyError from None - self.discard(value) - return value - - def clear(self): - """This is slow (creates N new iterators!) but effective.""" - try: - while True: - self.pop() - except KeyError: - pass - - def __ior__(self, it): - for value in it: - self.add(value) - return self - - def __iand__(self, it): - for value in (self - it): - self.discard(value) - return self - - def __ixor__(self, it): - if it is self: - self.clear() - else: - if not isinstance(it, Set): - it = self._from_iterable(it) - for value in it: - if value in self: - self.discard(value) - else: - self.add(value) - return self - - def __isub__(self, it): - if it is self: - self.clear() - else: - for value in it: - self.discard(value) - return self - -MutableSet.register(set) - - -### MAPPINGS ### - - -class Mapping(Collection): - - __slots__ = () - - """A Mapping is a generic container for associating key/value - pairs. - - This class provides concrete generic implementations of all - methods except for __getitem__, __iter__, and __len__. - - """ - - @abstractmethod - def __getitem__(self, key): - raise KeyError - - def get(self, key, default=None): - 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' - try: - return self[key] - except KeyError: - return default - - def __contains__(self, key): - try: - self[key] - except KeyError: - return False - else: - return True - - def keys(self): - "D.keys() -> a set-like object providing a view on D's keys" - return KeysView(self) - - def items(self): - "D.items() -> a set-like object providing a view on D's items" - return ItemsView(self) - - def values(self): - "D.values() -> an object providing a view on D's values" - return ValuesView(self) - - def __eq__(self, other): - if not isinstance(other, Mapping): - return NotImplemented - return dict(self.items()) == dict(other.items()) - - __reversed__ = None - -Mapping.register(mappingproxy) - - -class MappingView(Sized): - - __slots__ = '_mapping', - - def __init__(self, mapping): - self._mapping = mapping - - def __len__(self): - return len(self._mapping) - - def __repr__(self): - return '{0.__class__.__name__}({0._mapping!r})'.format(self) - - -class KeysView(MappingView, Set): - - __slots__ = () - - @classmethod - def _from_iterable(self, it): - return set(it) - - def __contains__(self, key): - return key in self._mapping - - def __iter__(self): - yield from self._mapping - -KeysView.register(dict_keys) - - -class ItemsView(MappingView, Set): - - __slots__ = () - - @classmethod - def _from_iterable(self, it): - return set(it) - - def __contains__(self, item): - key, value = item - try: - v = self._mapping[key] - except KeyError: - return False - else: - return v is value or v == value - - def __iter__(self): - for key in self._mapping: - yield (key, self._mapping[key]) - -ItemsView.register(dict_items) - - -class ValuesView(MappingView, Collection): - - __slots__ = () - - def __contains__(self, value): - for key in self._mapping: - v = self._mapping[key] - if v is value or v == value: - return True - return False - - def __iter__(self): - for key in self._mapping: - yield self._mapping[key] - -ValuesView.register(dict_values) - - -class MutableMapping(Mapping): - - __slots__ = () - - """A MutableMapping is a generic container for associating - key/value pairs. - - This class provides concrete generic implementations of all - methods except for __getitem__, __setitem__, __delitem__, - __iter__, and __len__. - - """ - - @abstractmethod - def __setitem__(self, key, value): - raise KeyError - - @abstractmethod - def __delitem__(self, key): - raise KeyError - - __marker = object() - - def pop(self, key, default=__marker): - '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - ''' - try: - value = self[key] - except KeyError: - if default is self.__marker: - raise - return default - else: - del self[key] - return value - - def popitem(self): - '''D.popitem() -> (k, v), remove and return some (key, value) pair - as a 2-tuple; but raise KeyError if D is empty. - ''' - try: - key = next(iter(self)) - except StopIteration: - raise KeyError from None - value = self[key] - del self[key] - return key, value - - def clear(self): - 'D.clear() -> None. Remove all items from D.' - try: - while True: - self.popitem() - except KeyError: - pass - - def update(*args, **kwds): - ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. - If E present and has a .keys() method, does: for k in E: D[k] = E[k] - If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v - In either case, this is followed by: for k, v in F.items(): D[k] = v - ''' - if not args: - raise TypeError("descriptor 'update' of 'MutableMapping' object " - "needs an argument") - self, *args = args - if len(args) > 1: - raise TypeError('update expected at most 1 arguments, got %d' % - len(args)) - if args: - other = args[0] - if isinstance(other, Mapping): - for key in other: - self[key] = other[key] - elif hasattr(other, "keys"): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - def setdefault(self, key, default=None): - 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' - try: - return self[key] - except KeyError: - self[key] = default - return default - -MutableMapping.register(dict) - - -### SEQUENCES ### - - -class Sequence(Reversible, Collection): - - """All the operations on a read-only sequence. - - Concrete subclasses must override __new__ or __init__, - __getitem__, and __len__. - """ - - __slots__ = () - - @abstractmethod - def __getitem__(self, index): - raise IndexError - - def __iter__(self): - i = 0 - try: - while True: - v = self[i] - yield v - i += 1 - except IndexError: - return - - def __contains__(self, value): - for v in self: - if v is value or v == value: - return True - return False - - def __reversed__(self): - for i in reversed(range(len(self))): - yield self[i] - - def index(self, value, start=0, stop=None): - '''S.index(value, [start, [stop]]) -> integer -- return first index of value. - Raises ValueError if the value is not present. - - Supporting start and stop arguments is optional, but - recommended. - ''' - if start is not None and start < 0: - start = max(len(self) + start, 0) - if stop is not None and stop < 0: - stop += len(self) - - i = start - while stop is None or i < stop: - try: - v = self[i] - if v is value or v == value: - return i - except IndexError: - break - i += 1 - raise ValueError - - def count(self, value): - 'S.count(value) -> integer -- return number of occurrences of value' - return sum(1 for v in self if v is value or v == value) - -Sequence.register(tuple) -Sequence.register(str) -Sequence.register(range) -Sequence.register(memoryview) - - -class ByteString(Sequence): - - """This unifies bytes and bytearray. - - XXX Should add all their methods. - """ - - __slots__ = () - -ByteString.register(bytes) -ByteString.register(bytearray) - - -class MutableSequence(Sequence): - - __slots__ = () - - """All the operations on a read-write sequence. - - Concrete subclasses must provide __new__ or __init__, - __getitem__, __setitem__, __delitem__, __len__, and insert(). - - """ - - @abstractmethod - def __setitem__(self, index, value): - raise IndexError - - @abstractmethod - def __delitem__(self, index): - raise IndexError - - @abstractmethod - def insert(self, index, value): - 'S.insert(index, value) -- insert value before index' - raise IndexError - - def append(self, value): - 'S.append(value) -- append value to the end of the sequence' - self.insert(len(self), value) - - def clear(self): - 'S.clear() -> None -- remove all items from S' - try: - while True: - self.pop() - except IndexError: - pass - - def reverse(self): - 'S.reverse() -- reverse *IN PLACE*' - n = len(self) - for i in range(n//2): - self[i], self[n-i-1] = self[n-i-1], self[i] - - def extend(self, values): - 'S.extend(iterable) -- extend sequence by appending elements from the iterable' - for v in values: - self.append(v) - - def pop(self, index=-1): - '''S.pop([index]) -> item -- remove and return item at index (default last). - Raise IndexError if list is empty or index is out of range. - ''' - v = self[index] - del self[index] - return v - - def remove(self, value): - '''S.remove(value) -- remove first occurrence of value. - Raise ValueError if the value is not present. - ''' - del self[self.index(value)] - - def __iadd__(self, values): - self.extend(values) - return self - -MutableSequence.register(list) -MutableSequence.register(bytearray) # Multiply inheriting, see ByteString diff --git a/experiment/simulation/backend/venv/lib/python3.7/_dummy_thread.py b/experiment/simulation/backend/venv/lib/python3.7/_dummy_thread.py deleted file mode 100644 index 2e46a07..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/_dummy_thread.py +++ /dev/null @@ -1,193 +0,0 @@ -"""Drop-in replacement for the thread module. - -Meant to be used as a brain-dead substitute so that threaded code does -not need to be rewritten for when the thread module is not present. - -Suggested usage is:: - - try: - import _thread - except ImportError: - import _dummy_thread as _thread - -""" -# Exports only things specified by thread documentation; -# skipping obsolete synonyms allocate(), start_new(), exit_thread(). -__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', - 'interrupt_main', 'LockType', 'RLock'] - -# A dummy value -TIMEOUT_MAX = 2**31 - -# NOTE: this module can be imported early in the extension building process, -# and so top level imports of other modules should be avoided. Instead, all -# imports are done when needed on a function-by-function basis. Since threads -# are disabled, the import lock should not be an issue anyway (??). - -error = RuntimeError - -def start_new_thread(function, args, kwargs={}): - """Dummy implementation of _thread.start_new_thread(). - - Compatibility is maintained by making sure that ``args`` is a - tuple and ``kwargs`` is a dictionary. If an exception is raised - and it is SystemExit (which can be done by _thread.exit()) it is - caught and nothing is done; all other exceptions are printed out - by using traceback.print_exc(). - - If the executed function calls interrupt_main the KeyboardInterrupt will be - raised when the function returns. - - """ - if type(args) != type(tuple()): - raise TypeError("2nd arg must be a tuple") - if type(kwargs) != type(dict()): - raise TypeError("3rd arg must be a dict") - global _main - _main = False - try: - function(*args, **kwargs) - except SystemExit: - pass - except: - import traceback - traceback.print_exc() - _main = True - global _interrupt - if _interrupt: - _interrupt = False - raise KeyboardInterrupt - -def exit(): - """Dummy implementation of _thread.exit().""" - raise SystemExit - -def get_ident(): - """Dummy implementation of _thread.get_ident(). - - Since this module should only be used when _threadmodule is not - available, it is safe to assume that the current process is the - only thread. Thus a constant can be safely returned. - """ - return 1 - -def allocate_lock(): - """Dummy implementation of _thread.allocate_lock().""" - return LockType() - -def stack_size(size=None): - """Dummy implementation of _thread.stack_size().""" - if size is not None: - raise error("setting thread stack size not supported") - return 0 - -def _set_sentinel(): - """Dummy implementation of _thread._set_sentinel().""" - return LockType() - -class LockType(object): - """Class implementing dummy implementation of _thread.LockType. - - Compatibility is maintained by maintaining self.locked_status - which is a boolean that stores the state of the lock. Pickling of - the lock, though, should not be done since if the _thread module is - then used with an unpickled ``lock()`` from here problems could - occur from this class not having atomic methods. - - """ - - def __init__(self): - self.locked_status = False - - def acquire(self, waitflag=None, timeout=-1): - """Dummy implementation of acquire(). - - For blocking calls, self.locked_status is automatically set to - True and returned appropriately based on value of - ``waitflag``. If it is non-blocking, then the value is - actually checked and not set if it is already acquired. This - is all done so that threading.Condition's assert statements - aren't triggered and throw a little fit. - - """ - if waitflag is None or waitflag: - self.locked_status = True - return True - else: - if not self.locked_status: - self.locked_status = True - return True - else: - if timeout > 0: - import time - time.sleep(timeout) - return False - - __enter__ = acquire - - def __exit__(self, typ, val, tb): - self.release() - - def release(self): - """Release the dummy lock.""" - # XXX Perhaps shouldn't actually bother to test? Could lead - # to problems for complex, threaded code. - if not self.locked_status: - raise error - self.locked_status = False - return True - - def locked(self): - return self.locked_status - - def __repr__(self): - return "<%s %s.%s object at %s>" % ( - "locked" if self.locked_status else "unlocked", - self.__class__.__module__, - self.__class__.__qualname__, - hex(id(self)) - ) - - -class RLock(LockType): - """Dummy implementation of threading._RLock. - - Re-entrant lock can be aquired multiple times and needs to be released - just as many times. This dummy implemention does not check wheter the - current thread actually owns the lock, but does accounting on the call - counts. - """ - def __init__(self): - super().__init__() - self._levels = 0 - - def acquire(self, waitflag=None, timeout=-1): - """Aquire the lock, can be called multiple times in succession. - """ - locked = super().acquire(waitflag, timeout) - if locked: - self._levels += 1 - return locked - - def release(self): - """Release needs to be called once for every call to acquire(). - """ - if self._levels == 0: - raise error - if self._levels == 1: - super().release() - self._levels -= 1 - -# Used to signal that interrupt_main was called in a "thread" -_interrupt = False -# True when not executing in a "thread" -_main = True - -def interrupt_main(): - """Set _interrupt flag to True to have start_new_thread raise - KeyboardInterrupt upon exiting.""" - if _main: - raise KeyboardInterrupt - else: - global _interrupt - _interrupt = True diff --git a/experiment/simulation/backend/venv/lib/python3.7/_weakrefset.py b/experiment/simulation/backend/venv/lib/python3.7/_weakrefset.py deleted file mode 100644 index 304c66f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/_weakrefset.py +++ /dev/null @@ -1,196 +0,0 @@ -# Access WeakSet through the weakref module. -# This code is separated-out because it is needed -# by abc.py to load everything else at startup. - -from _weakref import ref - -__all__ = ['WeakSet'] - - -class _IterationGuard: - # This context manager registers itself in the current iterators of the - # weak container, such as to delay all removals until the context manager - # exits. - # This technique should be relatively thread-safe (since sets are). - - def __init__(self, weakcontainer): - # Don't create cycles - self.weakcontainer = ref(weakcontainer) - - def __enter__(self): - w = self.weakcontainer() - if w is not None: - w._iterating.add(self) - return self - - def __exit__(self, e, t, b): - w = self.weakcontainer() - if w is not None: - s = w._iterating - s.remove(self) - if not s: - w._commit_removals() - - -class WeakSet: - def __init__(self, data=None): - self.data = set() - def _remove(item, selfref=ref(self)): - self = selfref() - if self is not None: - if self._iterating: - self._pending_removals.append(item) - else: - self.data.discard(item) - self._remove = _remove - # A list of keys to be removed - self._pending_removals = [] - self._iterating = set() - if data is not None: - self.update(data) - - def _commit_removals(self): - l = self._pending_removals - discard = self.data.discard - while l: - discard(l.pop()) - - def __iter__(self): - with _IterationGuard(self): - for itemref in self.data: - item = itemref() - if item is not None: - # Caveat: the iterator will keep a strong reference to - # `item` until it is resumed or closed. - yield item - - def __len__(self): - return len(self.data) - len(self._pending_removals) - - def __contains__(self, item): - try: - wr = ref(item) - except TypeError: - return False - return wr in self.data - - def __reduce__(self): - return (self.__class__, (list(self),), - getattr(self, '__dict__', None)) - - def add(self, item): - if self._pending_removals: - self._commit_removals() - self.data.add(ref(item, self._remove)) - - def clear(self): - if self._pending_removals: - self._commit_removals() - self.data.clear() - - def copy(self): - return self.__class__(self) - - def pop(self): - if self._pending_removals: - self._commit_removals() - while True: - try: - itemref = self.data.pop() - except KeyError: - raise KeyError('pop from empty WeakSet') from None - item = itemref() - if item is not None: - return item - - def remove(self, item): - if self._pending_removals: - self._commit_removals() - self.data.remove(ref(item)) - - def discard(self, item): - if self._pending_removals: - self._commit_removals() - self.data.discard(ref(item)) - - def update(self, other): - if self._pending_removals: - self._commit_removals() - for element in other: - self.add(element) - - def __ior__(self, other): - self.update(other) - return self - - def difference(self, other): - newset = self.copy() - newset.difference_update(other) - return newset - __sub__ = difference - - def difference_update(self, other): - self.__isub__(other) - def __isub__(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.difference_update(ref(item) for item in other) - return self - - def intersection(self, other): - return self.__class__(item for item in other if item in self) - __and__ = intersection - - def intersection_update(self, other): - self.__iand__(other) - def __iand__(self, other): - if self._pending_removals: - self._commit_removals() - self.data.intersection_update(ref(item) for item in other) - return self - - def issubset(self, other): - return self.data.issubset(ref(item) for item in other) - __le__ = issubset - - def __lt__(self, other): - return self.data < set(map(ref, other)) - - def issuperset(self, other): - return self.data.issuperset(ref(item) for item in other) - __ge__ = issuperset - - def __gt__(self, other): - return self.data > set(map(ref, other)) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.data == set(map(ref, other)) - - def symmetric_difference(self, other): - newset = self.copy() - newset.symmetric_difference_update(other) - return newset - __xor__ = symmetric_difference - - def symmetric_difference_update(self, other): - self.__ixor__(other) - def __ixor__(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.symmetric_difference_update(ref(item, self._remove) for item in other) - return self - - def union(self, other): - return self.__class__(e for s in (self, other) for e in s) - __or__ = union - - def isdisjoint(self, other): - return len(self.intersection(other)) == 0 diff --git a/experiment/simulation/backend/venv/lib/python3.7/abc.py b/experiment/simulation/backend/venv/lib/python3.7/abc.py deleted file mode 100644 index 7094141..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/abc.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Abstract Base Classes (ABCs) according to PEP 3119.""" - - -def abstractmethod(funcobj): - """A decorator indicating abstract methods. - - Requires that the metaclass is ABCMeta or derived from it. A - class that has a metaclass derived from ABCMeta cannot be - instantiated unless all of its abstract methods are overridden. - The abstract methods can be called using any of the normal - 'super' call mechanisms. - - Usage: - - class C(metaclass=ABCMeta): - @abstractmethod - def my_abstract_method(self, ...): - ... - """ - funcobj.__isabstractmethod__ = True - return funcobj - - -class abstractclassmethod(classmethod): - """A decorator indicating abstract classmethods. - - Similar to abstractmethod. - - Usage: - - class C(metaclass=ABCMeta): - @abstractclassmethod - def my_abstract_classmethod(cls, ...): - ... - - 'abstractclassmethod' is deprecated. Use 'classmethod' with - 'abstractmethod' instead. - """ - - __isabstractmethod__ = True - - def __init__(self, callable): - callable.__isabstractmethod__ = True - super().__init__(callable) - - -class abstractstaticmethod(staticmethod): - """A decorator indicating abstract staticmethods. - - Similar to abstractmethod. - - Usage: - - class C(metaclass=ABCMeta): - @abstractstaticmethod - def my_abstract_staticmethod(...): - ... - - 'abstractstaticmethod' is deprecated. Use 'staticmethod' with - 'abstractmethod' instead. - """ - - __isabstractmethod__ = True - - def __init__(self, callable): - callable.__isabstractmethod__ = True - super().__init__(callable) - - -class abstractproperty(property): - """A decorator indicating abstract properties. - - Requires that the metaclass is ABCMeta or derived from it. A - class that has a metaclass derived from ABCMeta cannot be - instantiated unless all of its abstract properties are overridden. - The abstract properties can be called using any of the normal - 'super' call mechanisms. - - Usage: - - class C(metaclass=ABCMeta): - @abstractproperty - def my_abstract_property(self): - ... - - This defines a read-only property; you can also define a read-write - abstract property using the 'long' form of property declaration: - - class C(metaclass=ABCMeta): - def getx(self): ... - def setx(self, value): ... - x = abstractproperty(getx, setx) - - 'abstractproperty' is deprecated. Use 'property' with 'abstractmethod' - instead. - """ - - __isabstractmethod__ = True - - -try: - from _abc import (get_cache_token, _abc_init, _abc_register, - _abc_instancecheck, _abc_subclasscheck, _get_dump, - _reset_registry, _reset_caches) -except ImportError: - from _py_abc import ABCMeta, get_cache_token - ABCMeta.__module__ = 'abc' -else: - class ABCMeta(type): - """Metaclass for defining Abstract Base Classes (ABCs). - - Use this metaclass to create an ABC. An ABC can be subclassed - directly, and then acts as a mix-in class. You can also register - unrelated concrete classes (even built-in classes) and unrelated - ABCs as 'virtual subclasses' -- these and their descendants will - be considered subclasses of the registering ABC by the built-in - issubclass() function, but the registering ABC won't show up in - their MRO (Method Resolution Order) nor will method - implementations defined by the registering ABC be callable (not - even via super()). - """ - def __new__(mcls, name, bases, namespace, **kwargs): - cls = super().__new__(mcls, name, bases, namespace, **kwargs) - _abc_init(cls) - return cls - - def register(cls, subclass): - """Register a virtual subclass of an ABC. - - Returns the subclass, to allow usage as a class decorator. - """ - return _abc_register(cls, subclass) - - def __instancecheck__(cls, instance): - """Override for isinstance(instance, cls).""" - return _abc_instancecheck(cls, instance) - - def __subclasscheck__(cls, subclass): - """Override for issubclass(subclass, cls).""" - return _abc_subclasscheck(cls, subclass) - - def _dump_registry(cls, file=None): - """Debug helper to print the ABC registry.""" - print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) - print(f"Inv. counter: {get_cache_token()}", file=file) - (_abc_registry, _abc_cache, _abc_negative_cache, - _abc_negative_cache_version) = _get_dump(cls) - print(f"_abc_registry: {_abc_registry!r}", file=file) - print(f"_abc_cache: {_abc_cache!r}", file=file) - print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) - print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", - file=file) - - def _abc_registry_clear(cls): - """Clear the registry (for debugging or testing).""" - _reset_registry(cls) - - def _abc_caches_clear(cls): - """Clear the caches (for debugging or testing).""" - _reset_caches(cls) - - -class ABC(metaclass=ABCMeta): - """Helper class that provides a standard way to create an ABC using - inheritance. - """ - __slots__ = () diff --git a/experiment/simulation/backend/venv/lib/python3.7/base64.py b/experiment/simulation/backend/venv/lib/python3.7/base64.py deleted file mode 100755 index 2e70223..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/base64.py +++ /dev/null @@ -1,595 +0,0 @@ -#! /usr/bin/env python3 - -"""Base16, Base32, Base64 (RFC 3548), Base85 and Ascii85 data encodings""" - -# Modified 04-Oct-1995 by Jack Jansen to use binascii module -# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support -# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere - -import re -import struct -import binascii - - -__all__ = [ - # Legacy interface exports traditional RFC 2045 Base64 encodings - 'encode', 'decode', 'encodebytes', 'decodebytes', - # Generalized interface for other encodings - 'b64encode', 'b64decode', 'b32encode', 'b32decode', - 'b16encode', 'b16decode', - # Base85 and Ascii85 encodings - 'b85encode', 'b85decode', 'a85encode', 'a85decode', - # Standard Base64 encoding - 'standard_b64encode', 'standard_b64decode', - # Some common Base64 alternatives. As referenced by RFC 3458, see thread - # starting at: - # - # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html - 'urlsafe_b64encode', 'urlsafe_b64decode', - ] - - -bytes_types = (bytes, bytearray) # Types acceptable as binary data - -def _bytes_from_decode_data(s): - if isinstance(s, str): - try: - return s.encode('ascii') - except UnicodeEncodeError: - raise ValueError('string argument should contain only ASCII characters') - if isinstance(s, bytes_types): - return s - try: - return memoryview(s).tobytes() - except TypeError: - raise TypeError("argument should be a bytes-like object or ASCII " - "string, not %r" % s.__class__.__name__) from None - - -# Base64 encoding/decoding uses binascii - -def b64encode(s, altchars=None): - """Encode the bytes-like object s using Base64 and return a bytes object. - - Optional altchars should be a byte string of length 2 which specifies an - alternative alphabet for the '+' and '/' characters. This allows an - application to e.g. generate url or filesystem safe Base64 strings. - """ - encoded = binascii.b2a_base64(s, newline=False) - if altchars is not None: - assert len(altchars) == 2, repr(altchars) - return encoded.translate(bytes.maketrans(b'+/', altchars)) - return encoded - - -def b64decode(s, altchars=None, validate=False): - """Decode the Base64 encoded bytes-like object or ASCII string s. - - Optional altchars must be a bytes-like object or ASCII string of length 2 - which specifies the alternative alphabet used instead of the '+' and '/' - characters. - - The result is returned as a bytes object. A binascii.Error is raised if - s is incorrectly padded. - - If validate is False (the default), characters that are neither in the - normal base-64 alphabet nor the alternative alphabet are discarded prior - to the padding check. If validate is True, these non-alphabet characters - in the input result in a binascii.Error. - """ - s = _bytes_from_decode_data(s) - if altchars is not None: - altchars = _bytes_from_decode_data(altchars) - assert len(altchars) == 2, repr(altchars) - s = s.translate(bytes.maketrans(altchars, b'+/')) - if validate and not re.fullmatch(b'[A-Za-z0-9+/]*={0,2}', s): - raise binascii.Error('Non-base64 digit found') - return binascii.a2b_base64(s) - - -def standard_b64encode(s): - """Encode bytes-like object s using the standard Base64 alphabet. - - The result is returned as a bytes object. - """ - return b64encode(s) - -def standard_b64decode(s): - """Decode bytes encoded with the standard Base64 alphabet. - - Argument s is a bytes-like object or ASCII string to decode. The result - is returned as a bytes object. A binascii.Error is raised if the input - is incorrectly padded. Characters that are not in the standard alphabet - are discarded prior to the padding check. - """ - return b64decode(s) - - -_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_') -_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/') - -def urlsafe_b64encode(s): - """Encode bytes using the URL- and filesystem-safe Base64 alphabet. - - Argument s is a bytes-like object to encode. The result is returned as a - bytes object. The alphabet uses '-' instead of '+' and '_' instead of - '/'. - """ - return b64encode(s).translate(_urlsafe_encode_translation) - -def urlsafe_b64decode(s): - """Decode bytes using the URL- and filesystem-safe Base64 alphabet. - - Argument s is a bytes-like object or ASCII string to decode. The result - is returned as a bytes object. A binascii.Error is raised if the input - is incorrectly padded. Characters that are not in the URL-safe base-64 - alphabet, and are not a plus '+' or slash '/', are discarded prior to the - padding check. - - The alphabet uses '-' instead of '+' and '_' instead of '/'. - """ - s = _bytes_from_decode_data(s) - s = s.translate(_urlsafe_decode_translation) - return b64decode(s) - - - -# Base32 encoding/decoding must be done in Python -_b32alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' -_b32tab2 = None -_b32rev = None - -def b32encode(s): - """Encode the bytes-like object s using Base32 and return a bytes object. - """ - global _b32tab2 - # Delay the initialization of the table to not waste memory - # if the function is never called - if _b32tab2 is None: - b32tab = [bytes((i,)) for i in _b32alphabet] - _b32tab2 = [a + b for a in b32tab for b in b32tab] - b32tab = None - - if not isinstance(s, bytes_types): - s = memoryview(s).tobytes() - leftover = len(s) % 5 - # Pad the last quantum with zero bits if necessary - if leftover: - s = s + b'\0' * (5 - leftover) # Don't use += ! - encoded = bytearray() - from_bytes = int.from_bytes - b32tab2 = _b32tab2 - for i in range(0, len(s), 5): - c = from_bytes(s[i: i + 5], 'big') - encoded += (b32tab2[c >> 30] + # bits 1 - 10 - b32tab2[(c >> 20) & 0x3ff] + # bits 11 - 20 - b32tab2[(c >> 10) & 0x3ff] + # bits 21 - 30 - b32tab2[c & 0x3ff] # bits 31 - 40 - ) - # Adjust for any leftover partial quanta - if leftover == 1: - encoded[-6:] = b'======' - elif leftover == 2: - encoded[-4:] = b'====' - elif leftover == 3: - encoded[-3:] = b'===' - elif leftover == 4: - encoded[-1:] = b'=' - return bytes(encoded) - -def b32decode(s, casefold=False, map01=None): - """Decode the Base32 encoded bytes-like object or ASCII string s. - - Optional casefold is a flag specifying whether a lowercase alphabet is - acceptable as input. For security purposes, the default is False. - - RFC 3548 allows for optional mapping of the digit 0 (zero) to the - letter O (oh), and for optional mapping of the digit 1 (one) to - either the letter I (eye) or letter L (el). The optional argument - map01 when not None, specifies which letter the digit 1 should be - mapped to (when map01 is not None, the digit 0 is always mapped to - the letter O). For security purposes the default is None, so that - 0 and 1 are not allowed in the input. - - The result is returned as a bytes object. A binascii.Error is raised if - the input is incorrectly padded or if there are non-alphabet - characters present in the input. - """ - global _b32rev - # Delay the initialization of the table to not waste memory - # if the function is never called - if _b32rev is None: - _b32rev = {v: k for k, v in enumerate(_b32alphabet)} - s = _bytes_from_decode_data(s) - if len(s) % 8: - raise binascii.Error('Incorrect padding') - # Handle section 2.4 zero and one mapping. The flag map01 will be either - # False, or the character to map the digit 1 (one) to. It should be - # either L (el) or I (eye). - if map01 is not None: - map01 = _bytes_from_decode_data(map01) - assert len(map01) == 1, repr(map01) - s = s.translate(bytes.maketrans(b'01', b'O' + map01)) - if casefold: - s = s.upper() - # Strip off pad characters from the right. We need to count the pad - # characters because this will tell us how many null bytes to remove from - # the end of the decoded string. - l = len(s) - s = s.rstrip(b'=') - padchars = l - len(s) - # Now decode the full quanta - decoded = bytearray() - b32rev = _b32rev - for i in range(0, len(s), 8): - quanta = s[i: i + 8] - acc = 0 - try: - for c in quanta: - acc = (acc << 5) + b32rev[c] - except KeyError: - raise binascii.Error('Non-base32 digit found') from None - decoded += acc.to_bytes(5, 'big') - # Process the last, partial quanta - if l % 8 or padchars not in {0, 1, 3, 4, 6}: - raise binascii.Error('Incorrect padding') - if padchars and decoded: - acc <<= 5 * padchars - last = acc.to_bytes(5, 'big') - leftover = (43 - 5 * padchars) // 8 # 1: 4, 3: 3, 4: 2, 6: 1 - decoded[-5:] = last[:leftover] - return bytes(decoded) - - -# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns -# lowercase. The RFC also recommends against accepting input case -# insensitively. -def b16encode(s): - """Encode the bytes-like object s using Base16 and return a bytes object. - """ - return binascii.hexlify(s).upper() - - -def b16decode(s, casefold=False): - """Decode the Base16 encoded bytes-like object or ASCII string s. - - Optional casefold is a flag specifying whether a lowercase alphabet is - acceptable as input. For security purposes, the default is False. - - The result is returned as a bytes object. A binascii.Error is raised if - s is incorrectly padded or if there are non-alphabet characters present - in the input. - """ - s = _bytes_from_decode_data(s) - if casefold: - s = s.upper() - if re.search(b'[^0-9A-F]', s): - raise binascii.Error('Non-base16 digit found') - return binascii.unhexlify(s) - -# -# Ascii85 encoding/decoding -# - -_a85chars = None -_a85chars2 = None -_A85START = b"<~" -_A85END = b"~>" - -def _85encode(b, chars, chars2, pad=False, foldnuls=False, foldspaces=False): - # Helper function for a85encode and b85encode - if not isinstance(b, bytes_types): - b = memoryview(b).tobytes() - - padding = (-len(b)) % 4 - if padding: - b = b + b'\0' * padding - words = struct.Struct('!%dI' % (len(b) // 4)).unpack(b) - - chunks = [b'z' if foldnuls and not word else - b'y' if foldspaces and word == 0x20202020 else - (chars2[word // 614125] + - chars2[word // 85 % 7225] + - chars[word % 85]) - for word in words] - - if padding and not pad: - if chunks[-1] == b'z': - chunks[-1] = chars[0] * 5 - chunks[-1] = chunks[-1][:-padding] - - return b''.join(chunks) - -def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False): - """Encode bytes-like object b using Ascii85 and return a bytes object. - - foldspaces is an optional flag that uses the special short sequence 'y' - instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This - feature is not supported by the "standard" Adobe encoding. - - wrapcol controls whether the output should have newline (b'\\n') characters - added to it. If this is non-zero, each output line will be at most this - many characters long. - - pad controls whether the input is padded to a multiple of 4 before - encoding. Note that the btoa implementation always pads. - - adobe controls whether the encoded byte sequence is framed with <~ and ~>, - which is used by the Adobe implementation. - """ - global _a85chars, _a85chars2 - # Delay the initialization of tables to not waste memory - # if the function is never called - if _a85chars is None: - _a85chars = [bytes((i,)) for i in range(33, 118)] - _a85chars2 = [(a + b) for a in _a85chars for b in _a85chars] - - result = _85encode(b, _a85chars, _a85chars2, pad, True, foldspaces) - - if adobe: - result = _A85START + result - if wrapcol: - wrapcol = max(2 if adobe else 1, wrapcol) - chunks = [result[i: i + wrapcol] - for i in range(0, len(result), wrapcol)] - if adobe: - if len(chunks[-1]) + 2 > wrapcol: - chunks.append(b'') - result = b'\n'.join(chunks) - if adobe: - result += _A85END - - return result - -def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): - """Decode the Ascii85 encoded bytes-like object or ASCII string b. - - foldspaces is a flag that specifies whether the 'y' short sequence should be - accepted as shorthand for 4 consecutive spaces (ASCII 0x20). This feature is - not supported by the "standard" Adobe encoding. - - adobe controls whether the input sequence is in Adobe Ascii85 format (i.e. - is framed with <~ and ~>). - - ignorechars should be a byte string containing characters to ignore from the - input. This should only contain whitespace characters, and by default - contains all whitespace characters in ASCII. - - The result is returned as a bytes object. - """ - b = _bytes_from_decode_data(b) - if adobe: - if not b.endswith(_A85END): - raise ValueError( - "Ascii85 encoded byte sequences must end " - "with {!r}".format(_A85END) - ) - if b.startswith(_A85START): - b = b[2:-2] # Strip off start/end markers - else: - b = b[:-2] - # - # We have to go through this stepwise, so as to ignore spaces and handle - # special short sequences - # - packI = struct.Struct('!I').pack - decoded = [] - decoded_append = decoded.append - curr = [] - curr_append = curr.append - curr_clear = curr.clear - for x in b + b'u' * 4: - if b'!'[0] <= x <= b'u'[0]: - curr_append(x) - if len(curr) == 5: - acc = 0 - for x in curr: - acc = 85 * acc + (x - 33) - try: - decoded_append(packI(acc)) - except struct.error: - raise ValueError('Ascii85 overflow') from None - curr_clear() - elif x == b'z'[0]: - if curr: - raise ValueError('z inside Ascii85 5-tuple') - decoded_append(b'\0\0\0\0') - elif foldspaces and x == b'y'[0]: - if curr: - raise ValueError('y inside Ascii85 5-tuple') - decoded_append(b'\x20\x20\x20\x20') - elif x in ignorechars: - # Skip whitespace - continue - else: - raise ValueError('Non-Ascii85 digit found: %c' % x) - - result = b''.join(decoded) - padding = 4 - len(curr) - if padding: - # Throw away the extra padding - result = result[:-padding] - return result - -# The following code is originally taken (with permission) from Mercurial - -_b85alphabet = (b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~") -_b85chars = None -_b85chars2 = None -_b85dec = None - -def b85encode(b, pad=False): - """Encode bytes-like object b in base85 format and return a bytes object. - - If pad is true, the input is padded with b'\\0' so its length is a multiple of - 4 bytes before encoding. - """ - global _b85chars, _b85chars2 - # Delay the initialization of tables to not waste memory - # if the function is never called - if _b85chars is None: - _b85chars = [bytes((i,)) for i in _b85alphabet] - _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars] - return _85encode(b, _b85chars, _b85chars2, pad) - -def b85decode(b): - """Decode the base85-encoded bytes-like object or ASCII string b - - The result is returned as a bytes object. - """ - global _b85dec - # Delay the initialization of tables to not waste memory - # if the function is never called - if _b85dec is None: - _b85dec = [None] * 256 - for i, c in enumerate(_b85alphabet): - _b85dec[c] = i - - b = _bytes_from_decode_data(b) - padding = (-len(b)) % 5 - b = b + b'~' * padding - out = [] - packI = struct.Struct('!I').pack - for i in range(0, len(b), 5): - chunk = b[i:i + 5] - acc = 0 - try: - for c in chunk: - acc = acc * 85 + _b85dec[c] - except TypeError: - for j, c in enumerate(chunk): - if _b85dec[c] is None: - raise ValueError('bad base85 character at position %d' - % (i + j)) from None - raise - try: - out.append(packI(acc)) - except struct.error: - raise ValueError('base85 overflow in hunk starting at byte %d' - % i) from None - - result = b''.join(out) - if padding: - result = result[:-padding] - return result - -# Legacy interface. This code could be cleaned up since I don't believe -# binascii has any line length limitations. It just doesn't seem worth it -# though. The files should be opened in binary mode. - -MAXLINESIZE = 76 # Excluding the CRLF -MAXBINSIZE = (MAXLINESIZE//4)*3 - -def encode(input, output): - """Encode a file; input and output are binary files.""" - while True: - s = input.read(MAXBINSIZE) - if not s: - break - while len(s) < MAXBINSIZE: - ns = input.read(MAXBINSIZE-len(s)) - if not ns: - break - s += ns - line = binascii.b2a_base64(s) - output.write(line) - - -def decode(input, output): - """Decode a file; input and output are binary files.""" - while True: - line = input.readline() - if not line: - break - s = binascii.a2b_base64(line) - output.write(s) - -def _input_type_check(s): - try: - m = memoryview(s) - except TypeError as err: - msg = "expected bytes-like object, not %s" % s.__class__.__name__ - raise TypeError(msg) from err - if m.format not in ('c', 'b', 'B'): - msg = ("expected single byte elements, not %r from %s" % - (m.format, s.__class__.__name__)) - raise TypeError(msg) - if m.ndim != 1: - msg = ("expected 1-D data, not %d-D data from %s" % - (m.ndim, s.__class__.__name__)) - raise TypeError(msg) - - -def encodebytes(s): - """Encode a bytestring into a bytes object containing multiple lines - of base-64 data.""" - _input_type_check(s) - pieces = [] - for i in range(0, len(s), MAXBINSIZE): - chunk = s[i : i + MAXBINSIZE] - pieces.append(binascii.b2a_base64(chunk)) - return b"".join(pieces) - -def encodestring(s): - """Legacy alias of encodebytes().""" - import warnings - warnings.warn("encodestring() is a deprecated alias since 3.1, " - "use encodebytes()", - DeprecationWarning, 2) - return encodebytes(s) - - -def decodebytes(s): - """Decode a bytestring of base-64 data into a bytes object.""" - _input_type_check(s) - return binascii.a2b_base64(s) - -def decodestring(s): - """Legacy alias of decodebytes().""" - import warnings - warnings.warn("decodestring() is a deprecated alias since Python 3.1, " - "use decodebytes()", - DeprecationWarning, 2) - return decodebytes(s) - - -# Usable as a script... -def main(): - """Small main program""" - import sys, getopt - try: - opts, args = getopt.getopt(sys.argv[1:], 'deut') - except getopt.error as msg: - sys.stdout = sys.stderr - print(msg) - print("""usage: %s [-d|-e|-u|-t] [file|-] - -d, -u: decode - -e: encode (default) - -t: encode and decode string 'Aladdin:open sesame'"""%sys.argv[0]) - sys.exit(2) - func = encode - for o, a in opts: - if o == '-e': func = encode - if o == '-d': func = decode - if o == '-u': func = decode - if o == '-t': test(); return - if args and args[0] != '-': - with open(args[0], 'rb') as f: - func(f, sys.stdout.buffer) - else: - func(sys.stdin.buffer, sys.stdout.buffer) - - -def test(): - s0 = b"Aladdin:open sesame" - print(repr(s0)) - s1 = encodebytes(s0) - print(repr(s1)) - s2 = decodebytes(s1) - print(repr(s2)) - assert s0 == s2 - - -if __name__ == '__main__': - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/bisect.py b/experiment/simulation/backend/venv/lib/python3.7/bisect.py deleted file mode 100644 index 7732c63..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/bisect.py +++ /dev/null @@ -1,92 +0,0 @@ -"""Bisection algorithms.""" - -def insort_right(a, x, lo=0, hi=None): - """Insert item x in list a, and keep it sorted assuming a is sorted. - - If x is already in a, insert it to the right of the rightmost x. - - Optional args lo (default 0) and hi (default len(a)) bound the - slice of a to be searched. - """ - - if lo < 0: - raise ValueError('lo must be non-negative') - if hi is None: - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if x < a[mid]: hi = mid - else: lo = mid+1 - a.insert(lo, x) - -def bisect_right(a, x, lo=0, hi=None): - """Return the index where to insert item x in list a, assuming a is sorted. - - The return value i is such that all e in a[:i] have e <= x, and all e in - a[i:] have e > x. So if x already appears in the list, a.insert(x) will - insert just after the rightmost x already there. - - Optional args lo (default 0) and hi (default len(a)) bound the - slice of a to be searched. - """ - - if lo < 0: - raise ValueError('lo must be non-negative') - if hi is None: - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if x < a[mid]: hi = mid - else: lo = mid+1 - return lo - -def insort_left(a, x, lo=0, hi=None): - """Insert item x in list a, and keep it sorted assuming a is sorted. - - If x is already in a, insert it to the left of the leftmost x. - - Optional args lo (default 0) and hi (default len(a)) bound the - slice of a to be searched. - """ - - if lo < 0: - raise ValueError('lo must be non-negative') - if hi is None: - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if a[mid] < x: lo = mid+1 - else: hi = mid - a.insert(lo, x) - - -def bisect_left(a, x, lo=0, hi=None): - """Return the index where to insert item x in list a, assuming a is sorted. - - The return value i is such that all e in a[:i] have e < x, and all e in - a[i:] have e >= x. So if x already appears in the list, a.insert(x) will - insert just before the leftmost x already there. - - Optional args lo (default 0) and hi (default len(a)) bound the - slice of a to be searched. - """ - - if lo < 0: - raise ValueError('lo must be non-negative') - if hi is None: - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if a[mid] < x: lo = mid+1 - else: hi = mid - return lo - -# Overwrite above definitions with a fast C implementation -try: - from _bisect import * -except ImportError: - pass - -# Create aliases -bisect = bisect_right -insort = insort_right diff --git a/experiment/simulation/backend/venv/lib/python3.7/codecs.py b/experiment/simulation/backend/venv/lib/python3.7/codecs.py deleted file mode 100644 index 5d95f25..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/codecs.py +++ /dev/null @@ -1,1125 +0,0 @@ -""" codecs -- Python Codec Registry, API and helpers. - - -Written by Marc-Andre Lemburg (mal@lemburg.com). - -(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. - -""" - -import builtins -import sys - -### Registry and builtin stateless codec functions - -try: - from _codecs import * -except ImportError as why: - raise SystemError('Failed to load the builtin codecs: %s' % why) - -__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE", - "BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE", - "BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE", - "BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE", - "CodecInfo", "Codec", "IncrementalEncoder", "IncrementalDecoder", - "StreamReader", "StreamWriter", - "StreamReaderWriter", "StreamRecoder", - "getencoder", "getdecoder", "getincrementalencoder", - "getincrementaldecoder", "getreader", "getwriter", - "encode", "decode", "iterencode", "iterdecode", - "strict_errors", "ignore_errors", "replace_errors", - "xmlcharrefreplace_errors", - "backslashreplace_errors", "namereplace_errors", - "register_error", "lookup_error"] - -### Constants - -# -# Byte Order Mark (BOM = ZERO WIDTH NO-BREAK SPACE = U+FEFF) -# and its possible byte string values -# for UTF8/UTF16/UTF32 output and little/big endian machines -# - -# UTF-8 -BOM_UTF8 = b'\xef\xbb\xbf' - -# UTF-16, little endian -BOM_LE = BOM_UTF16_LE = b'\xff\xfe' - -# UTF-16, big endian -BOM_BE = BOM_UTF16_BE = b'\xfe\xff' - -# UTF-32, little endian -BOM_UTF32_LE = b'\xff\xfe\x00\x00' - -# UTF-32, big endian -BOM_UTF32_BE = b'\x00\x00\xfe\xff' - -if sys.byteorder == 'little': - - # UTF-16, native endianness - BOM = BOM_UTF16 = BOM_UTF16_LE - - # UTF-32, native endianness - BOM_UTF32 = BOM_UTF32_LE - -else: - - # UTF-16, native endianness - BOM = BOM_UTF16 = BOM_UTF16_BE - - # UTF-32, native endianness - BOM_UTF32 = BOM_UTF32_BE - -# Old broken names (don't use in new code) -BOM32_LE = BOM_UTF16_LE -BOM32_BE = BOM_UTF16_BE -BOM64_LE = BOM_UTF32_LE -BOM64_BE = BOM_UTF32_BE - - -### Codec base classes (defining the API) - -class CodecInfo(tuple): - """Codec details when looking up the codec registry""" - - # Private API to allow Python 3.4 to blacklist the known non-Unicode - # codecs in the standard library. A more general mechanism to - # reliably distinguish test encodings from other codecs will hopefully - # be defined for Python 3.5 - # - # See http://bugs.python.org/issue19619 - _is_text_encoding = True # Assume codecs are text encodings by default - - def __new__(cls, encode, decode, streamreader=None, streamwriter=None, - incrementalencoder=None, incrementaldecoder=None, name=None, - *, _is_text_encoding=None): - self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter)) - self.name = name - self.encode = encode - self.decode = decode - self.incrementalencoder = incrementalencoder - self.incrementaldecoder = incrementaldecoder - self.streamwriter = streamwriter - self.streamreader = streamreader - if _is_text_encoding is not None: - self._is_text_encoding = _is_text_encoding - return self - - def __repr__(self): - return "<%s.%s object for encoding %s at %#x>" % \ - (self.__class__.__module__, self.__class__.__qualname__, - self.name, id(self)) - -class Codec: - - """ Defines the interface for stateless encoders/decoders. - - The .encode()/.decode() methods may use different error - handling schemes by providing the errors argument. These - string values are predefined: - - 'strict' - raise a ValueError error (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace' - replace with a suitable replacement character; - Python will use the official U+FFFD REPLACEMENT - CHARACTER for the builtin Unicode codecs on - decoding and '?' on encoding. - 'surrogateescape' - replace with private code points U+DCnn. - 'xmlcharrefreplace' - Replace with the appropriate XML - character reference (only for encoding). - 'backslashreplace' - Replace with backslashed escape sequences. - 'namereplace' - Replace with \\N{...} escape sequences - (only for encoding). - - The set of allowed values can be extended via register_error. - - """ - def encode(self, input, errors='strict'): - - """ Encodes the object input and returns a tuple (output - object, length consumed). - - errors defines the error handling to apply. It defaults to - 'strict' handling. - - The method may not store state in the Codec instance. Use - StreamWriter for codecs which have to keep state in order to - make encoding efficient. - - The encoder must be able to handle zero length input and - return an empty object of the output object type in this - situation. - - """ - raise NotImplementedError - - def decode(self, input, errors='strict'): - - """ Decodes the object input and returns a tuple (output - object, length consumed). - - input must be an object which provides the bf_getreadbuf - buffer slot. Python strings, buffer objects and memory - mapped files are examples of objects providing this slot. - - errors defines the error handling to apply. It defaults to - 'strict' handling. - - The method may not store state in the Codec instance. Use - StreamReader for codecs which have to keep state in order to - make decoding efficient. - - The decoder must be able to handle zero length input and - return an empty object of the output object type in this - situation. - - """ - raise NotImplementedError - -class IncrementalEncoder(object): - """ - An IncrementalEncoder encodes an input in multiple steps. The input can - be passed piece by piece to the encode() method. The IncrementalEncoder - remembers the state of the encoding process between calls to encode(). - """ - def __init__(self, errors='strict'): - """ - Creates an IncrementalEncoder instance. - - The IncrementalEncoder may use different error handling schemes by - providing the errors keyword argument. See the module docstring - for a list of possible values. - """ - self.errors = errors - self.buffer = "" - - def encode(self, input, final=False): - """ - Encodes input and returns the resulting object. - """ - raise NotImplementedError - - def reset(self): - """ - Resets the encoder to the initial state. - """ - - def getstate(self): - """ - Return the current state of the encoder. - """ - return 0 - - def setstate(self, state): - """ - Set the current state of the encoder. state must have been - returned by getstate(). - """ - -class BufferedIncrementalEncoder(IncrementalEncoder): - """ - This subclass of IncrementalEncoder can be used as the baseclass for an - incremental encoder if the encoder must keep some of the output in a - buffer between calls to encode(). - """ - def __init__(self, errors='strict'): - IncrementalEncoder.__init__(self, errors) - # unencoded input that is kept between calls to encode() - self.buffer = "" - - def _buffer_encode(self, input, errors, final): - # Overwrite this method in subclasses: It must encode input - # and return an (output, length consumed) tuple - raise NotImplementedError - - def encode(self, input, final=False): - # encode input (taking the buffer into account) - data = self.buffer + input - (result, consumed) = self._buffer_encode(data, self.errors, final) - # keep unencoded input until the next call - self.buffer = data[consumed:] - return result - - def reset(self): - IncrementalEncoder.reset(self) - self.buffer = "" - - def getstate(self): - return self.buffer or 0 - - def setstate(self, state): - self.buffer = state or "" - -class IncrementalDecoder(object): - """ - An IncrementalDecoder decodes an input in multiple steps. The input can - be passed piece by piece to the decode() method. The IncrementalDecoder - remembers the state of the decoding process between calls to decode(). - """ - def __init__(self, errors='strict'): - """ - Create an IncrementalDecoder instance. - - The IncrementalDecoder may use different error handling schemes by - providing the errors keyword argument. See the module docstring - for a list of possible values. - """ - self.errors = errors - - def decode(self, input, final=False): - """ - Decode input and returns the resulting object. - """ - raise NotImplementedError - - def reset(self): - """ - Reset the decoder to the initial state. - """ - - def getstate(self): - """ - Return the current state of the decoder. - - This must be a (buffered_input, additional_state_info) tuple. - buffered_input must be a bytes object containing bytes that - were passed to decode() that have not yet been converted. - additional_state_info must be a non-negative integer - representing the state of the decoder WITHOUT yet having - processed the contents of buffered_input. In the initial state - and after reset(), getstate() must return (b"", 0). - """ - return (b"", 0) - - def setstate(self, state): - """ - Set the current state of the decoder. - - state must have been returned by getstate(). The effect of - setstate((b"", 0)) must be equivalent to reset(). - """ - -class BufferedIncrementalDecoder(IncrementalDecoder): - """ - This subclass of IncrementalDecoder can be used as the baseclass for an - incremental decoder if the decoder must be able to handle incomplete - byte sequences. - """ - def __init__(self, errors='strict'): - IncrementalDecoder.__init__(self, errors) - # undecoded input that is kept between calls to decode() - self.buffer = b"" - - def _buffer_decode(self, input, errors, final): - # Overwrite this method in subclasses: It must decode input - # and return an (output, length consumed) tuple - raise NotImplementedError - - def decode(self, input, final=False): - # decode input (taking the buffer into account) - data = self.buffer + input - (result, consumed) = self._buffer_decode(data, self.errors, final) - # keep undecoded input until the next call - self.buffer = data[consumed:] - return result - - def reset(self): - IncrementalDecoder.reset(self) - self.buffer = b"" - - def getstate(self): - # additional state info is always 0 - return (self.buffer, 0) - - def setstate(self, state): - # ignore additional state info - self.buffer = state[0] - -# -# The StreamWriter and StreamReader class provide generic working -# interfaces which can be used to implement new encoding submodules -# very easily. See encodings/utf_8.py for an example on how this is -# done. -# - -class StreamWriter(Codec): - - def __init__(self, stream, errors='strict'): - - """ Creates a StreamWriter instance. - - stream must be a file-like object open for writing. - - The StreamWriter may use different error handling - schemes by providing the errors keyword argument. These - parameters are predefined: - - 'strict' - raise a ValueError (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace'- replace with a suitable replacement character - 'xmlcharrefreplace' - Replace with the appropriate XML - character reference. - 'backslashreplace' - Replace with backslashed escape - sequences. - 'namereplace' - Replace with \\N{...} escape sequences. - - The set of allowed parameter values can be extended via - register_error. - """ - self.stream = stream - self.errors = errors - - def write(self, object): - - """ Writes the object's contents encoded to self.stream. - """ - data, consumed = self.encode(object, self.errors) - self.stream.write(data) - - def writelines(self, list): - - """ Writes the concatenated list of strings to the stream - using .write(). - """ - self.write(''.join(list)) - - def reset(self): - - """ Flushes and resets the codec buffers used for keeping state. - - Calling this method should ensure that the data on the - output is put into a clean state, that allows appending - of new fresh data without having to rescan the whole - stream to recover state. - - """ - pass - - def seek(self, offset, whence=0): - self.stream.seek(offset, whence) - if whence == 0 and offset == 0: - self.reset() - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - - def __enter__(self): - return self - - def __exit__(self, type, value, tb): - self.stream.close() - -### - -class StreamReader(Codec): - - charbuffertype = str - - def __init__(self, stream, errors='strict'): - - """ Creates a StreamReader instance. - - stream must be a file-like object open for reading. - - The StreamReader may use different error handling - schemes by providing the errors keyword argument. These - parameters are predefined: - - 'strict' - raise a ValueError (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace'- replace with a suitable replacement character - 'backslashreplace' - Replace with backslashed escape sequences; - - The set of allowed parameter values can be extended via - register_error. - """ - self.stream = stream - self.errors = errors - self.bytebuffer = b"" - self._empty_charbuffer = self.charbuffertype() - self.charbuffer = self._empty_charbuffer - self.linebuffer = None - - def decode(self, input, errors='strict'): - raise NotImplementedError - - def read(self, size=-1, chars=-1, firstline=False): - - """ Decodes data from the stream self.stream and returns the - resulting object. - - chars indicates the number of decoded code points or bytes to - return. read() will never return more data than requested, - but it might return less, if there is not enough available. - - size indicates the approximate maximum number of decoded - bytes or code points to read for decoding. The decoder - can modify this setting as appropriate. The default value - -1 indicates to read and decode as much as possible. size - is intended to prevent having to decode huge files in one - step. - - If firstline is true, and a UnicodeDecodeError happens - after the first line terminator in the input only the first line - will be returned, the rest of the input will be kept until the - next call to read(). - - The method should use a greedy read strategy, meaning that - it should read as much data as is allowed within the - definition of the encoding and the given size, e.g. if - optional encoding endings or state markers are available - on the stream, these should be read too. - """ - # If we have lines cached, first merge them back into characters - if self.linebuffer: - self.charbuffer = self._empty_charbuffer.join(self.linebuffer) - self.linebuffer = None - - if chars < 0: - # For compatibility with other read() methods that take a - # single argument - chars = size - - # read until we get the required number of characters (if available) - while True: - # can the request be satisfied from the character buffer? - if chars >= 0: - if len(self.charbuffer) >= chars: - break - # we need more data - if size < 0: - newdata = self.stream.read() - else: - newdata = self.stream.read(size) - # decode bytes (those remaining from the last call included) - data = self.bytebuffer + newdata - if not data: - break - try: - newchars, decodedbytes = self.decode(data, self.errors) - except UnicodeDecodeError as exc: - if firstline: - newchars, decodedbytes = \ - self.decode(data[:exc.start], self.errors) - lines = newchars.splitlines(keepends=True) - if len(lines)<=1: - raise - else: - raise - # keep undecoded bytes until the next call - self.bytebuffer = data[decodedbytes:] - # put new characters in the character buffer - self.charbuffer += newchars - # there was no data available - if not newdata: - break - if chars < 0: - # Return everything we've got - result = self.charbuffer - self.charbuffer = self._empty_charbuffer - else: - # Return the first chars characters - result = self.charbuffer[:chars] - self.charbuffer = self.charbuffer[chars:] - return result - - def readline(self, size=None, keepends=True): - - """ Read one line from the input stream and return the - decoded data. - - size, if given, is passed as size argument to the - read() method. - - """ - # If we have lines cached from an earlier read, return - # them unconditionally - if self.linebuffer: - line = self.linebuffer[0] - del self.linebuffer[0] - if len(self.linebuffer) == 1: - # revert to charbuffer mode; we might need more data - # next time - self.charbuffer = self.linebuffer[0] - self.linebuffer = None - if not keepends: - line = line.splitlines(keepends=False)[0] - return line - - readsize = size or 72 - line = self._empty_charbuffer - # If size is given, we call read() only once - while True: - data = self.read(readsize, firstline=True) - if data: - # If we're at a "\r" read one extra character (which might - # be a "\n") to get a proper line ending. If the stream is - # temporarily exhausted we return the wrong line ending. - if (isinstance(data, str) and data.endswith("\r")) or \ - (isinstance(data, bytes) and data.endswith(b"\r")): - data += self.read(size=1, chars=1) - - line += data - lines = line.splitlines(keepends=True) - if lines: - if len(lines) > 1: - # More than one line result; the first line is a full line - # to return - line = lines[0] - del lines[0] - if len(lines) > 1: - # cache the remaining lines - lines[-1] += self.charbuffer - self.linebuffer = lines - self.charbuffer = None - else: - # only one remaining line, put it back into charbuffer - self.charbuffer = lines[0] + self.charbuffer - if not keepends: - line = line.splitlines(keepends=False)[0] - break - line0withend = lines[0] - line0withoutend = lines[0].splitlines(keepends=False)[0] - if line0withend != line0withoutend: # We really have a line end - # Put the rest back together and keep it until the next call - self.charbuffer = self._empty_charbuffer.join(lines[1:]) + \ - self.charbuffer - if keepends: - line = line0withend - else: - line = line0withoutend - break - # we didn't get anything or this was our only try - if not data or size is not None: - if line and not keepends: - line = line.splitlines(keepends=False)[0] - break - if readsize < 8000: - readsize *= 2 - return line - - def readlines(self, sizehint=None, keepends=True): - - """ Read all lines available on the input stream - and return them as a list. - - Line breaks are implemented using the codec's decoder - method and are included in the list entries. - - sizehint, if given, is ignored since there is no efficient - way to finding the true end-of-line. - - """ - data = self.read() - return data.splitlines(keepends) - - def reset(self): - - """ Resets the codec buffers used for keeping state. - - Note that no stream repositioning should take place. - This method is primarily intended to be able to recover - from decoding errors. - - """ - self.bytebuffer = b"" - self.charbuffer = self._empty_charbuffer - self.linebuffer = None - - def seek(self, offset, whence=0): - """ Set the input stream's current position. - - Resets the codec buffers used for keeping state. - """ - self.stream.seek(offset, whence) - self.reset() - - def __next__(self): - - """ Return the next decoded line from the input stream.""" - line = self.readline() - if line: - return line - raise StopIteration - - def __iter__(self): - return self - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - - def __enter__(self): - return self - - def __exit__(self, type, value, tb): - self.stream.close() - -### - -class StreamReaderWriter: - - """ StreamReaderWriter instances allow wrapping streams which - work in both read and write modes. - - The design is such that one can use the factory functions - returned by the codec.lookup() function to construct the - instance. - - """ - # Optional attributes set by the file wrappers below - encoding = 'unknown' - - def __init__(self, stream, Reader, Writer, errors='strict'): - - """ Creates a StreamReaderWriter instance. - - stream must be a Stream-like object. - - Reader, Writer must be factory functions or classes - providing the StreamReader, StreamWriter interface resp. - - Error handling is done in the same way as defined for the - StreamWriter/Readers. - - """ - self.stream = stream - self.reader = Reader(stream, errors) - self.writer = Writer(stream, errors) - self.errors = errors - - def read(self, size=-1): - - return self.reader.read(size) - - def readline(self, size=None): - - return self.reader.readline(size) - - def readlines(self, sizehint=None): - - return self.reader.readlines(sizehint) - - def __next__(self): - - """ Return the next decoded line from the input stream.""" - return next(self.reader) - - def __iter__(self): - return self - - def write(self, data): - - return self.writer.write(data) - - def writelines(self, list): - - return self.writer.writelines(list) - - def reset(self): - - self.reader.reset() - self.writer.reset() - - def seek(self, offset, whence=0): - self.stream.seek(offset, whence) - self.reader.reset() - if whence == 0 and offset == 0: - self.writer.reset() - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - - # these are needed to make "with StreamReaderWriter(...)" work properly - - def __enter__(self): - return self - - def __exit__(self, type, value, tb): - self.stream.close() - -### - -class StreamRecoder: - - """ StreamRecoder instances translate data from one encoding to another. - - They use the complete set of APIs returned by the - codecs.lookup() function to implement their task. - - Data written to the StreamRecoder is first decoded into an - intermediate format (depending on the "decode" codec) and then - written to the underlying stream using an instance of the provided - Writer class. - - In the other direction, data is read from the underlying stream using - a Reader instance and then encoded and returned to the caller. - - """ - # Optional attributes set by the file wrappers below - data_encoding = 'unknown' - file_encoding = 'unknown' - - def __init__(self, stream, encode, decode, Reader, Writer, - errors='strict'): - - """ Creates a StreamRecoder instance which implements a two-way - conversion: encode and decode work on the frontend (the - data visible to .read() and .write()) while Reader and Writer - work on the backend (the data in stream). - - You can use these objects to do transparent - transcodings from e.g. latin-1 to utf-8 and back. - - stream must be a file-like object. - - encode and decode must adhere to the Codec interface; Reader and - Writer must be factory functions or classes providing the - StreamReader and StreamWriter interfaces resp. - - Error handling is done in the same way as defined for the - StreamWriter/Readers. - - """ - self.stream = stream - self.encode = encode - self.decode = decode - self.reader = Reader(stream, errors) - self.writer = Writer(stream, errors) - self.errors = errors - - def read(self, size=-1): - - data = self.reader.read(size) - data, bytesencoded = self.encode(data, self.errors) - return data - - def readline(self, size=None): - - if size is None: - data = self.reader.readline() - else: - data = self.reader.readline(size) - data, bytesencoded = self.encode(data, self.errors) - return data - - def readlines(self, sizehint=None): - - data = self.reader.read() - data, bytesencoded = self.encode(data, self.errors) - return data.splitlines(keepends=True) - - def __next__(self): - - """ Return the next decoded line from the input stream.""" - data = next(self.reader) - data, bytesencoded = self.encode(data, self.errors) - return data - - def __iter__(self): - return self - - def write(self, data): - - data, bytesdecoded = self.decode(data, self.errors) - return self.writer.write(data) - - def writelines(self, list): - - data = b''.join(list) - data, bytesdecoded = self.decode(data, self.errors) - return self.writer.write(data) - - def reset(self): - - self.reader.reset() - self.writer.reset() - - def seek(self, offset, whence=0): - # Seeks must be propagated to both the readers and writers - # as they might need to reset their internal buffers. - self.reader.seek(offset, whence) - self.writer.seek(offset, whence) - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - - def __enter__(self): - return self - - def __exit__(self, type, value, tb): - self.stream.close() - -### Shortcuts - -def open(filename, mode='r', encoding=None, errors='strict', buffering=1): - - """ Open an encoded file using the given mode and return - a wrapped version providing transparent encoding/decoding. - - Note: The wrapped version will only accept the object format - defined by the codecs, i.e. Unicode objects for most builtin - codecs. Output is also codec dependent and will usually be - Unicode as well. - - Underlying encoded files are always opened in binary mode. - The default file mode is 'r', meaning to open the file in read mode. - - encoding specifies the encoding which is to be used for the - file. - - errors may be given to define the error handling. It defaults - to 'strict' which causes ValueErrors to be raised in case an - encoding error occurs. - - buffering has the same meaning as for the builtin open() API. - It defaults to line buffered. - - The returned wrapped file object provides an extra attribute - .encoding which allows querying the used encoding. This - attribute is only available if an encoding was specified as - parameter. - - """ - if encoding is not None and \ - 'b' not in mode: - # Force opening of the file in binary mode - mode = mode + 'b' - file = builtins.open(filename, mode, buffering) - if encoding is None: - return file - - try: - info = lookup(encoding) - srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) - # Add attributes to simplify introspection - srw.encoding = encoding - return srw - except: - file.close() - raise - -def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): - - """ Return a wrapped version of file which provides transparent - encoding translation. - - Data written to the wrapped file is decoded according - to the given data_encoding and then encoded to the underlying - file using file_encoding. The intermediate data type - will usually be Unicode but depends on the specified codecs. - - Bytes read from the file are decoded using file_encoding and then - passed back to the caller encoded using data_encoding. - - If file_encoding is not given, it defaults to data_encoding. - - errors may be given to define the error handling. It defaults - to 'strict' which causes ValueErrors to be raised in case an - encoding error occurs. - - The returned wrapped file object provides two extra attributes - .data_encoding and .file_encoding which reflect the given - parameters of the same name. The attributes can be used for - introspection by Python programs. - - """ - if file_encoding is None: - file_encoding = data_encoding - data_info = lookup(data_encoding) - file_info = lookup(file_encoding) - sr = StreamRecoder(file, data_info.encode, data_info.decode, - file_info.streamreader, file_info.streamwriter, errors) - # Add attributes to simplify introspection - sr.data_encoding = data_encoding - sr.file_encoding = file_encoding - return sr - -### Helpers for codec lookup - -def getencoder(encoding): - - """ Lookup up the codec for the given encoding and return - its encoder function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding).encode - -def getdecoder(encoding): - - """ Lookup up the codec for the given encoding and return - its decoder function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding).decode - -def getincrementalencoder(encoding): - - """ Lookup up the codec for the given encoding and return - its IncrementalEncoder class or factory function. - - Raises a LookupError in case the encoding cannot be found - or the codecs doesn't provide an incremental encoder. - - """ - encoder = lookup(encoding).incrementalencoder - if encoder is None: - raise LookupError(encoding) - return encoder - -def getincrementaldecoder(encoding): - - """ Lookup up the codec for the given encoding and return - its IncrementalDecoder class or factory function. - - Raises a LookupError in case the encoding cannot be found - or the codecs doesn't provide an incremental decoder. - - """ - decoder = lookup(encoding).incrementaldecoder - if decoder is None: - raise LookupError(encoding) - return decoder - -def getreader(encoding): - - """ Lookup up the codec for the given encoding and return - its StreamReader class or factory function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding).streamreader - -def getwriter(encoding): - - """ Lookup up the codec for the given encoding and return - its StreamWriter class or factory function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding).streamwriter - -def iterencode(iterator, encoding, errors='strict', **kwargs): - """ - Encoding iterator. - - Encodes the input strings from the iterator using an IncrementalEncoder. - - errors and kwargs are passed through to the IncrementalEncoder - constructor. - """ - encoder = getincrementalencoder(encoding)(errors, **kwargs) - for input in iterator: - output = encoder.encode(input) - if output: - yield output - output = encoder.encode("", True) - if output: - yield output - -def iterdecode(iterator, encoding, errors='strict', **kwargs): - """ - Decoding iterator. - - Decodes the input strings from the iterator using an IncrementalDecoder. - - errors and kwargs are passed through to the IncrementalDecoder - constructor. - """ - decoder = getincrementaldecoder(encoding)(errors, **kwargs) - for input in iterator: - output = decoder.decode(input) - if output: - yield output - output = decoder.decode(b"", True) - if output: - yield output - -### Helpers for charmap-based codecs - -def make_identity_dict(rng): - - """ make_identity_dict(rng) -> dict - - Return a dictionary where elements of the rng sequence are - mapped to themselves. - - """ - return {i:i for i in rng} - -def make_encoding_map(decoding_map): - - """ Creates an encoding map from a decoding map. - - If a target mapping in the decoding map occurs multiple - times, then that target is mapped to None (undefined mapping), - causing an exception when encountered by the charmap codec - during translation. - - One example where this happens is cp875.py which decodes - multiple character to \\u001a. - - """ - m = {} - for k,v in decoding_map.items(): - if not v in m: - m[v] = k - else: - m[v] = None - return m - -### error handlers - -try: - strict_errors = lookup_error("strict") - ignore_errors = lookup_error("ignore") - replace_errors = lookup_error("replace") - xmlcharrefreplace_errors = lookup_error("xmlcharrefreplace") - backslashreplace_errors = lookup_error("backslashreplace") - namereplace_errors = lookup_error("namereplace") -except LookupError: - # In --disable-unicode builds, these error handler are missing - strict_errors = None - ignore_errors = None - replace_errors = None - xmlcharrefreplace_errors = None - backslashreplace_errors = None - namereplace_errors = None - -# Tell modulefinder that using codecs probably needs the encodings -# package -_false = 0 -if _false: - import encodings - -### Tests - -if __name__ == '__main__': - - # Make stdout translate Latin-1 output into UTF-8 output - sys.stdout = EncodedFile(sys.stdout, 'latin-1', 'utf-8') - - # Have stdin translate Latin-1 input into UTF-8 input - sys.stdin = EncodedFile(sys.stdin, 'utf-8', 'latin-1') diff --git a/experiment/simulation/backend/venv/lib/python3.7/collections b/experiment/simulation/backend/venv/lib/python3.7/collections deleted file mode 120000 index 9b59f26..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/collections +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/collections \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/config-3.7m-x86_64-linux-gnu b/experiment/simulation/backend/venv/lib/python3.7/config-3.7m-x86_64-linux-gnu deleted file mode 120000 index 9e6ede4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/config-3.7m-x86_64-linux-gnu +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/copy.py b/experiment/simulation/backend/venv/lib/python3.7/copy.py deleted file mode 100644 index e634c43..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/copy.py +++ /dev/null @@ -1,314 +0,0 @@ -"""Generic (shallow and deep) copying operations. - -Interface summary: - - import copy - - x = copy.copy(y) # make a shallow copy of y - x = copy.deepcopy(y) # make a deep copy of y - -For module specific errors, copy.Error is raised. - -The difference between shallow and deep copying is only relevant for -compound objects (objects that contain other objects, like lists or -class instances). - -- A shallow copy constructs a new compound object and then (to the - extent possible) inserts *the same objects* into it that the - original contains. - -- A deep copy constructs a new compound object and then, recursively, - inserts *copies* into it of the objects found in the original. - -Two problems often exist with deep copy operations that don't exist -with shallow copy operations: - - a) recursive objects (compound objects that, directly or indirectly, - contain a reference to themselves) may cause a recursive loop - - b) because deep copy copies *everything* it may copy too much, e.g. - administrative data structures that should be shared even between - copies - -Python's deep copy operation avoids these problems by: - - a) keeping a table of objects already copied during the current - copying pass - - b) letting user-defined classes override the copying operation or the - set of components copied - -This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. - -Classes can use the same interfaces to control copying that they use -to control pickling: they can define methods called __getinitargs__(), -__getstate__() and __setstate__(). See the documentation for module -"pickle" for information on these methods. -""" - -import types -import weakref -from copyreg import dispatch_table - -class Error(Exception): - pass -error = Error # backward compatibility - -try: - from org.python.core import PyStringMap -except ImportError: - PyStringMap = None - -__all__ = ["Error", "copy", "deepcopy"] - -def copy(x): - """Shallow copy operation on arbitrary Python objects. - - See the module's __doc__ string for more info. - """ - - cls = type(x) - - copier = _copy_dispatch.get(cls) - if copier: - return copier(x) - - try: - issc = issubclass(cls, type) - except TypeError: # cls is not a class - issc = False - if issc: - # treat it as a regular class: - return _copy_immutable(x) - - copier = getattr(cls, "__copy__", None) - if copier: - return copier(x) - - reductor = dispatch_table.get(cls) - if reductor: - rv = reductor(x) - else: - reductor = getattr(x, "__reduce_ex__", None) - if reductor: - rv = reductor(4) - else: - reductor = getattr(x, "__reduce__", None) - if reductor: - rv = reductor() - else: - raise Error("un(shallow)copyable object of type %s" % cls) - - if isinstance(rv, str): - return x - return _reconstruct(x, None, *rv) - - -_copy_dispatch = d = {} - -def _copy_immutable(x): - return x -for t in (type(None), int, float, bool, complex, str, tuple, - bytes, frozenset, type, range, slice, property, - types.BuiltinFunctionType, type(Ellipsis), type(NotImplemented), - types.FunctionType, weakref.ref): - d[t] = _copy_immutable -t = getattr(types, "CodeType", None) -if t is not None: - d[t] = _copy_immutable - -d[list] = list.copy -d[dict] = dict.copy -d[set] = set.copy -d[bytearray] = bytearray.copy - -if PyStringMap is not None: - d[PyStringMap] = PyStringMap.copy - -del d, t - -def deepcopy(x, memo=None, _nil=[]): - """Deep copy operation on arbitrary Python objects. - - See the module's __doc__ string for more info. - """ - - if memo is None: - memo = {} - - d = id(x) - y = memo.get(d, _nil) - if y is not _nil: - return y - - cls = type(x) - - copier = _deepcopy_dispatch.get(cls) - if copier: - y = copier(x, memo) - else: - try: - issc = issubclass(cls, type) - except TypeError: # cls is not a class (old Boost; see SF #502085) - issc = 0 - if issc: - y = _deepcopy_atomic(x, memo) - else: - copier = getattr(x, "__deepcopy__", None) - if copier: - y = copier(memo) - else: - reductor = dispatch_table.get(cls) - if reductor: - rv = reductor(x) - else: - reductor = getattr(x, "__reduce_ex__", None) - if reductor: - rv = reductor(4) - else: - reductor = getattr(x, "__reduce__", None) - if reductor: - rv = reductor() - else: - raise Error( - "un(deep)copyable object of type %s" % cls) - if isinstance(rv, str): - y = x - else: - y = _reconstruct(x, memo, *rv) - - # If is its own copy, don't memoize. - if y is not x: - memo[d] = y - _keep_alive(x, memo) # Make sure x lives at least as long as d - return y - -_deepcopy_dispatch = d = {} - -def _deepcopy_atomic(x, memo): - return x -d[type(None)] = _deepcopy_atomic -d[type(Ellipsis)] = _deepcopy_atomic -d[type(NotImplemented)] = _deepcopy_atomic -d[int] = _deepcopy_atomic -d[float] = _deepcopy_atomic -d[bool] = _deepcopy_atomic -d[complex] = _deepcopy_atomic -d[bytes] = _deepcopy_atomic -d[str] = _deepcopy_atomic -try: - d[types.CodeType] = _deepcopy_atomic -except AttributeError: - pass -d[type] = _deepcopy_atomic -d[types.BuiltinFunctionType] = _deepcopy_atomic -d[types.FunctionType] = _deepcopy_atomic -d[weakref.ref] = _deepcopy_atomic -d[property] = _deepcopy_atomic - -def _deepcopy_list(x, memo, deepcopy=deepcopy): - y = [] - memo[id(x)] = y - append = y.append - for a in x: - append(deepcopy(a, memo)) - return y -d[list] = _deepcopy_list - -def _deepcopy_tuple(x, memo, deepcopy=deepcopy): - y = [deepcopy(a, memo) for a in x] - # We're not going to put the tuple in the memo, but it's still important we - # check for it, in case the tuple contains recursive mutable structures. - try: - return memo[id(x)] - except KeyError: - pass - for k, j in zip(x, y): - if k is not j: - y = tuple(y) - break - else: - y = x - return y -d[tuple] = _deepcopy_tuple - -def _deepcopy_dict(x, memo, deepcopy=deepcopy): - y = {} - memo[id(x)] = y - for key, value in x.items(): - y[deepcopy(key, memo)] = deepcopy(value, memo) - return y -d[dict] = _deepcopy_dict -if PyStringMap is not None: - d[PyStringMap] = _deepcopy_dict - -def _deepcopy_method(x, memo): # Copy instance methods - return type(x)(x.__func__, deepcopy(x.__self__, memo)) -d[types.MethodType] = _deepcopy_method - -del d - -def _keep_alive(x, memo): - """Keeps a reference to the object x in the memo. - - Because we remember objects by their id, we have - to assure that possibly temporary objects are kept - alive by referencing them. - We store a reference at the id of the memo, which should - normally not be used unless someone tries to deepcopy - the memo itself... - """ - try: - memo[id(memo)].append(x) - except KeyError: - # aha, this is the first one :-) - memo[id(memo)]=[x] - -def _reconstruct(x, memo, func, args, - state=None, listiter=None, dictiter=None, - deepcopy=deepcopy): - deep = memo is not None - if deep and args: - args = (deepcopy(arg, memo) for arg in args) - y = func(*args) - if deep: - memo[id(x)] = y - - if state is not None: - if deep: - state = deepcopy(state, memo) - if hasattr(y, '__setstate__'): - y.__setstate__(state) - else: - if isinstance(state, tuple) and len(state) == 2: - state, slotstate = state - else: - slotstate = None - if state is not None: - y.__dict__.update(state) - if slotstate is not None: - for key, value in slotstate.items(): - setattr(y, key, value) - - if listiter is not None: - if deep: - for item in listiter: - item = deepcopy(item, memo) - y.append(item) - else: - for item in listiter: - y.append(item) - if dictiter is not None: - if deep: - for key, value in dictiter: - key = deepcopy(key, memo) - value = deepcopy(value, memo) - y[key] = value - else: - for key, value in dictiter: - y[key] = value - return y - -del types, weakref, PyStringMap diff --git a/experiment/simulation/backend/venv/lib/python3.7/copyreg.py b/experiment/simulation/backend/venv/lib/python3.7/copyreg.py deleted file mode 100644 index bbe1af4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/copyreg.py +++ /dev/null @@ -1,206 +0,0 @@ -"""Helper to provide extensibility for pickle. - -This is only useful to add pickle support for extension types defined in -C, not for instances of user-defined classes. -""" - -__all__ = ["pickle", "constructor", - "add_extension", "remove_extension", "clear_extension_cache"] - -dispatch_table = {} - -def pickle(ob_type, pickle_function, constructor_ob=None): - if not callable(pickle_function): - raise TypeError("reduction functions must be callable") - dispatch_table[ob_type] = pickle_function - - # The constructor_ob function is a vestige of safe for unpickling. - # There is no reason for the caller to pass it anymore. - if constructor_ob is not None: - constructor(constructor_ob) - -def constructor(object): - if not callable(object): - raise TypeError("constructors must be callable") - -# Example: provide pickling support for complex numbers. - -try: - complex -except NameError: - pass -else: - - def pickle_complex(c): - return complex, (c.real, c.imag) - - pickle(complex, pickle_complex, complex) - -# Support for pickling new-style objects - -def _reconstructor(cls, base, state): - if base is object: - obj = object.__new__(cls) - else: - obj = base.__new__(cls, state) - if base.__init__ != object.__init__: - base.__init__(obj, state) - return obj - -_HEAPTYPE = 1<<9 - -# Python code for object.__reduce_ex__ for protocols 0 and 1 - -def _reduce_ex(self, proto): - assert proto < 2 - for base in self.__class__.__mro__: - if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: - break - else: - base = object # not really reachable - if base is object: - state = None - else: - if base is self.__class__: - raise TypeError("can't pickle %s objects" % base.__name__) - state = base(self) - args = (self.__class__, base, state) - try: - getstate = self.__getstate__ - except AttributeError: - if getattr(self, "__slots__", None): - raise TypeError("a class that defines __slots__ without " - "defining __getstate__ cannot be pickled") from None - try: - dict = self.__dict__ - except AttributeError: - dict = None - else: - dict = getstate() - if dict: - return _reconstructor, args, dict - else: - return _reconstructor, args - -# Helper for __reduce_ex__ protocol 2 - -def __newobj__(cls, *args): - return cls.__new__(cls, *args) - -def __newobj_ex__(cls, args, kwargs): - """Used by pickle protocol 4, instead of __newobj__ to allow classes with - keyword-only arguments to be pickled correctly. - """ - return cls.__new__(cls, *args, **kwargs) - -def _slotnames(cls): - """Return a list of slot names for a given class. - - This needs to find slots defined by the class and its bases, so we - can't simply return the __slots__ attribute. We must walk down - the Method Resolution Order and concatenate the __slots__ of each - class found there. (This assumes classes don't modify their - __slots__ attribute to misrepresent their slots after the class is - defined.) - """ - - # Get the value from a cache in the class if possible - names = cls.__dict__.get("__slotnames__") - if names is not None: - return names - - # Not cached -- calculate the value - names = [] - if not hasattr(cls, "__slots__"): - # This class has no slots - pass - else: - # Slots found -- gather slot names from all base classes - for c in cls.__mro__: - if "__slots__" in c.__dict__: - slots = c.__dict__['__slots__'] - # if class has a single slot, it can be given as a string - if isinstance(slots, str): - slots = (slots,) - for name in slots: - # special descriptors - if name in ("__dict__", "__weakref__"): - continue - # mangled names - elif name.startswith('__') and not name.endswith('__'): - stripped = c.__name__.lstrip('_') - if stripped: - names.append('_%s%s' % (stripped, name)) - else: - names.append(name) - else: - names.append(name) - - # Cache the outcome in the class if at all possible - try: - cls.__slotnames__ = names - except: - pass # But don't die if we can't - - return names - -# A registry of extension codes. This is an ad-hoc compression -# mechanism. Whenever a global reference to , is about -# to be pickled, the (, ) tuple is looked up here to see -# if it is a registered extension code for it. Extension codes are -# universal, so that the meaning of a pickle does not depend on -# context. (There are also some codes reserved for local use that -# don't have this restriction.) Codes are positive ints; 0 is -# reserved. - -_extension_registry = {} # key -> code -_inverted_registry = {} # code -> key -_extension_cache = {} # code -> object -# Don't ever rebind those names: pickling grabs a reference to them when -# it's initialized, and won't see a rebinding. - -def add_extension(module, name, code): - """Register an extension code.""" - code = int(code) - if not 1 <= code <= 0x7fffffff: - raise ValueError("code out of range") - key = (module, name) - if (_extension_registry.get(key) == code and - _inverted_registry.get(code) == key): - return # Redundant registrations are benign - if key in _extension_registry: - raise ValueError("key %s is already registered with code %s" % - (key, _extension_registry[key])) - if code in _inverted_registry: - raise ValueError("code %s is already in use for key %s" % - (code, _inverted_registry[code])) - _extension_registry[key] = code - _inverted_registry[code] = key - -def remove_extension(module, name, code): - """Unregister an extension code. For testing only.""" - key = (module, name) - if (_extension_registry.get(key) != code or - _inverted_registry.get(code) != key): - raise ValueError("key %s is not registered with code %s" % - (key, code)) - del _extension_registry[key] - del _inverted_registry[code] - if code in _extension_cache: - del _extension_cache[code] - -def clear_extension_cache(): - _extension_cache.clear() - -# Standard extension code assignments - -# Reserved ranges - -# First Last Count Purpose -# 1 127 127 Reserved for Python standard library -# 128 191 64 Reserved for Zope -# 192 239 48 Reserved for 3rd parties -# 240 255 16 Reserved for private use (will never be assigned) -# 256 Inf Inf Reserved for future assignment - -# Extension codes are assigned by the Python Software Foundation. diff --git a/experiment/simulation/backend/venv/lib/python3.7/distutils/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/distutils/__init__.py deleted file mode 100644 index b9b0f24..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/distutils/__init__.py +++ /dev/null @@ -1,134 +0,0 @@ -import os -import sys -import warnings - -# opcode is not a virtualenv module, so we can use it to find the stdlib -# Important! To work on pypy, this must be a module that resides in the -# lib-python/modified-x.y.z directory -import opcode - -dirname = os.path.dirname - -distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils") -if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): - warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?") -else: - __path__.insert(0, distutils_path) # noqa: F821 - if sys.version_info < (3, 4): - import imp - - real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY)) - else: - import importlib.machinery - - distutils_path = os.path.join(distutils_path, "__init__.py") - loader = importlib.machinery.SourceFileLoader("_virtualenv_distutils", distutils_path) - if sys.version_info < (3, 5): - import types - - real_distutils = types.ModuleType(loader.name) - else: - import importlib.util - - spec = importlib.util.spec_from_loader(loader.name, loader) - real_distutils = importlib.util.module_from_spec(spec) - loader.exec_module(real_distutils) - - # Copy the relevant attributes - try: - __revision__ = real_distutils.__revision__ - except AttributeError: - pass - __version__ = real_distutils.__version__ - -from distutils import dist, sysconfig # isort:skip - -try: - basestring -except NameError: - basestring = str - -# patch build_ext (distutils doesn't know how to get the libs directory -# path on windows - it hardcodes the paths around the patched sys.prefix) - -if sys.platform == "win32": - from distutils.command.build_ext import build_ext as old_build_ext - - class build_ext(old_build_ext): - def finalize_options(self): - if self.library_dirs is None: - self.library_dirs = [] - elif isinstance(self.library_dirs, basestring): - self.library_dirs = self.library_dirs.split(os.pathsep) - - self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) - old_build_ext.finalize_options(self) - - from distutils.command import build_ext as build_ext_module - - build_ext_module.build_ext = build_ext - -# distutils.dist patches: - -old_find_config_files = dist.Distribution.find_config_files - - -def find_config_files(self): - found = old_find_config_files(self) - if os.name == "posix": - user_filename = ".pydistutils.cfg" - else: - user_filename = "pydistutils.cfg" - user_filename = os.path.join(sys.prefix, user_filename) - if os.path.isfile(user_filename): - for item in list(found): - if item.endswith("pydistutils.cfg"): - found.remove(item) - found.append(user_filename) - return found - - -dist.Distribution.find_config_files = find_config_files - -# distutils.sysconfig patches: - -old_get_python_inc = sysconfig.get_python_inc - - -def sysconfig_get_python_inc(plat_specific=0, prefix=None): - if prefix is None: - prefix = sys.real_prefix - return old_get_python_inc(plat_specific, prefix) - - -sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ -sysconfig.get_python_inc = sysconfig_get_python_inc - -old_get_python_lib = sysconfig.get_python_lib - - -def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): - if standard_lib and prefix is None: - prefix = sys.real_prefix - return old_get_python_lib(plat_specific, standard_lib, prefix) - - -sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ -sysconfig.get_python_lib = sysconfig_get_python_lib - -old_get_config_vars = sysconfig.get_config_vars - - -def sysconfig_get_config_vars(*args): - real_vars = old_get_config_vars(*args) - if sys.platform == "win32": - lib_dir = os.path.join(sys.real_prefix, "libs") - if isinstance(real_vars, dict) and "LIBDIR" not in real_vars: - real_vars["LIBDIR"] = lib_dir # asked for all - elif isinstance(real_vars, list) and "LIBDIR" in args: - real_vars = real_vars + [lib_dir] # asked for list - return real_vars - - -sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ -sysconfig.get_config_vars = sysconfig_get_config_vars diff --git a/experiment/simulation/backend/venv/lib/python3.7/distutils/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/distutils/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index d181e6b5c1b83eaedb30b999139d018dd18e8379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3191 zcma)8OLN=E5yk)@2vQ_PN!G*K7vo5q<;qJsw&Qm>iPsy~Rvaa@>&j-QDvJU!LkSQG za0ifVspyk@PUV^#Rh3Js@@w`u*IeSikW;=M(zL8SBw%44-90mn?ytY$qk6q+;fdMb zzFS+etbftu&EsS6E4+Ejwk%-@Hn8}#XPlY2&27^=+>ut|CM8~?e&U(7B%P#u#)N%l zbKgiR(m!J}9obbR^k?kARs(5Is=_&A%u0Wd3zM3#U~4l=vZOBD155qgoYdeA*_bSf zl3>yop73NNY4)8nmoKHtSS<6EnGe1wo0C_POOsVmqW$=q+0Vy*|2Ed^d|j?jHso4z z`HW$YEhF8;9xKUvllMt3*RbvbGyhP2Kvr^X@{wF3UyrMDDQWT6H&(jlTJk3c)xR=z zi&^yh)=KR^Suc`F=^WT^61k+piV6{oEN>+*0YTZ1eLi#SVLA+#hs&I>twyU{P(_G<^n zzIM^@)!^-6!Td07oh$@FoW?~EbVkQ*TbUIltZ3WXB|BZg#!;5`<2_w^9;Y|1x0$Z= z4 cHI-0OsnD&2GXKRKotPxh>If}M8Z{6QxTgjp}vgwbG-Q<(TuGGWpv=H z4P z-KTLcZ`XNk5cgE5ju8o!>uQ|GXLVDc=H+>i&dG=YOHB*vXjlZvz?2+?zUa+2SEzV1%a*x z!7vkt0~*(Y;CsM#sxh0JuQ}IT#xW-2cj;7uhtJ+c0D+TUgMa}B1+sd|Ub2EEfDY(y zL)b6v)D_N48!~6&7Nx`+Bg?aS8DpmQUu+frn4Pl6)}J?CI%8*2A<9&b#%xj@8}j`A z(Ki-m3uMnQA~^2q(kRR07bi`?e;%|>)ZaTo&&QJJR#<*`o7O8x9G6})~3sF^cp zZ|%mY?+d}zOFwewDR#&y(-zWOWuEP_Ceqx%m|pb>G!dnO9_p#&P523lW7I6luTfYD zCBYs;a%v+~Y`5*0k5W|JdYMA8CyQW;IdDh>#;A`5VG-mb8O8lLQY~0sba-POZF;mN9+^|Fy##ejl>)1Xep7|f%qFC@XpJE?gqrw-V z5&>~S3!?weV_2s!o_Sm&k3Yja!fT#49zVe>{|*fS`!CixVDrMkJzoN-J)$kZxjbft z52AZ0oH08ntA}G7`EVW(4U(<`9f!_3@Dv}jvAxIEvEvNNs)AEEAlA#d_w>t0kH7q? zUDYdZ5;cSD5pI(yIDJZ1KT|^k;B(NW1gix!bOS_%x`JWb(Qc^ra$Ye!N4xMcjv@xV z7_iIlruf{!C)g=(qM2f|$(DggdewD0!!|5UKqI!EO&(0$Gxg*@4^;|k#s_AjC==6y z(`7he%8x3K$cls^xQ=8U6_ z#z+?A3s_FY9K@~U5pF$vYoHsyE^y!V4h#8(Qkl~DNAM;Pfg*xXbVV!r%d6<((3M@# z(bU$#RjIlV^7rO}=tS9Yh??rm?-WD%YL(2Eeq_d*bGx~Jk3o~hC3t8EOHs}9#=C^0 z+7KF^(B&WySwty6XM#+qt7Jlj$rnj;4vVToD#G14{1OE!y0x_bU>dB41jW3M#s@F? zCExb#4c1~cy9V6)_9o^H!>s5rCa$eIHgrvJf@e2v8|#{^TB>19vs$w~*LVCy-}RiT N2d1;%_Wpv;{tLJQRjU91 diff --git a/experiment/simulation/backend/venv/lib/python3.7/distutils/distutils.cfg b/experiment/simulation/backend/venv/lib/python3.7/distutils/distutils.cfg deleted file mode 100644 index 1af230e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/distutils/distutils.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# This is a config file local to this virtualenv installation -# You may include options that will be used by all distutils commands, -# and by easy_install. For instance: -# -# [easy_install] -# find_links = http://mylocalsite diff --git a/experiment/simulation/backend/venv/lib/python3.7/encodings b/experiment/simulation/backend/venv/lib/python3.7/encodings deleted file mode 120000 index bc6d310..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/encodings +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/encodings \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/enum.py b/experiment/simulation/backend/venv/lib/python3.7/enum.py deleted file mode 100644 index d0b03b4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/enum.py +++ /dev/null @@ -1,910 +0,0 @@ -import sys -from types import MappingProxyType, DynamicClassAttribute - -# try _collections first to reduce startup cost -try: - from _collections import OrderedDict -except ImportError: - from collections import OrderedDict - - -__all__ = [ - 'EnumMeta', - 'Enum', 'IntEnum', 'Flag', 'IntFlag', - 'auto', 'unique', - ] - - -def _is_descriptor(obj): - """Returns True if obj is a descriptor, False otherwise.""" - return ( - hasattr(obj, '__get__') or - hasattr(obj, '__set__') or - hasattr(obj, '__delete__')) - - -def _is_dunder(name): - """Returns True if a __dunder__ name, False otherwise.""" - return (len(name) > 4 and - name[:2] == name[-2:] == '__' and - name[2] != '_' and - name[-3] != '_') - - -def _is_sunder(name): - """Returns True if a _sunder_ name, False otherwise.""" - return (len(name) > 2 and - name[0] == name[-1] == '_' and - name[1:2] != '_' and - name[-2:-1] != '_') - - -def _make_class_unpicklable(cls): - """Make the given class un-picklable.""" - def _break_on_call_reduce(self, proto): - raise TypeError('%r cannot be pickled' % self) - cls.__reduce_ex__ = _break_on_call_reduce - cls.__module__ = '' - -_auto_null = object() -class auto: - """ - Instances are replaced with an appropriate value in Enum class suites. - """ - value = _auto_null - - -class _EnumDict(dict): - """Track enum member order and ensure member names are not reused. - - EnumMeta will use the names found in self._member_names as the - enumeration member names. - - """ - def __init__(self): - super().__init__() - self._member_names = [] - self._last_values = [] - self._ignore = [] - - def __setitem__(self, key, value): - """Changes anything not dundered or not a descriptor. - - If an enum member name is used twice, an error is raised; duplicate - values are not checked for. - - Single underscore (sunder) names are reserved. - - """ - if _is_sunder(key): - if key not in ( - '_order_', '_create_pseudo_member_', - '_generate_next_value_', '_missing_', '_ignore_', - ): - raise ValueError('_names_ are reserved for future Enum use') - if key == '_generate_next_value_': - setattr(self, '_generate_next_value', value) - elif key == '_ignore_': - if isinstance(value, str): - value = value.replace(',',' ').split() - else: - value = list(value) - self._ignore = value - already = set(value) & set(self._member_names) - if already: - raise ValueError('_ignore_ cannot specify already set names: %r' % (already, )) - elif _is_dunder(key): - if key == '__order__': - key = '_order_' - elif key in self._member_names: - # descriptor overwriting an enum? - raise TypeError('Attempted to reuse key: %r' % key) - elif key in self._ignore: - pass - elif not _is_descriptor(value): - if key in self: - # enum overwriting a descriptor? - raise TypeError('%r already defined as: %r' % (key, self[key])) - if isinstance(value, auto): - if value.value == _auto_null: - value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:]) - value = value.value - self._member_names.append(key) - self._last_values.append(value) - super().__setitem__(key, value) - - -# Dummy value for Enum as EnumMeta explicitly checks for it, but of course -# until EnumMeta finishes running the first time the Enum class doesn't exist. -# This is also why there are checks in EnumMeta like `if Enum is not None` -Enum = None - - -class EnumMeta(type): - """Metaclass for Enum""" - @classmethod - def __prepare__(metacls, cls, bases): - # create the namespace dict - enum_dict = _EnumDict() - # inherit previous flags and _generate_next_value_ function - member_type, first_enum = metacls._get_mixins_(bases) - if first_enum is not None: - enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None) - return enum_dict - - def __new__(metacls, cls, bases, classdict): - # an Enum class is final once enumeration items have been defined; it - # cannot be mixed with other types (int, float, etc.) if it has an - # inherited __new__ unless a new __new__ is defined (or the resulting - # class will fail). - # - # remove any keys listed in _ignore_ - classdict.setdefault('_ignore_', []).append('_ignore_') - ignore = classdict['_ignore_'] - for key in ignore: - classdict.pop(key, None) - member_type, first_enum = metacls._get_mixins_(bases) - __new__, save_new, use_args = metacls._find_new_(classdict, member_type, - first_enum) - - # save enum items into separate mapping so they don't get baked into - # the new class - enum_members = {k: classdict[k] for k in classdict._member_names} - for name in classdict._member_names: - del classdict[name] - - # adjust the sunders - _order_ = classdict.pop('_order_', None) - - # check for illegal enum names (any others?) - invalid_names = set(enum_members) & {'mro', ''} - if invalid_names: - raise ValueError('Invalid enum member name: {0}'.format( - ','.join(invalid_names))) - - # create a default docstring if one has not been provided - if '__doc__' not in classdict: - classdict['__doc__'] = 'An enumeration.' - - # create our new Enum type - enum_class = super().__new__(metacls, cls, bases, classdict) - enum_class._member_names_ = [] # names in definition order - enum_class._member_map_ = OrderedDict() # name->value map - enum_class._member_type_ = member_type - - # save DynamicClassAttribute attributes from super classes so we know - # if we can take the shortcut of storing members in the class dict - dynamic_attributes = {k for c in enum_class.mro() - for k, v in c.__dict__.items() - if isinstance(v, DynamicClassAttribute)} - - # Reverse value->name map for hashable values. - enum_class._value2member_map_ = {} - - # If a custom type is mixed into the Enum, and it does not know how - # to pickle itself, pickle.dumps will succeed but pickle.loads will - # fail. Rather than have the error show up later and possibly far - # from the source, sabotage the pickle protocol for this class so - # that pickle.dumps also fails. - # - # However, if the new class implements its own __reduce_ex__, do not - # sabotage -- it's on them to make sure it works correctly. We use - # __reduce_ex__ instead of any of the others as it is preferred by - # pickle over __reduce__, and it handles all pickle protocols. - if '__reduce_ex__' not in classdict: - if member_type is not object: - methods = ('__getnewargs_ex__', '__getnewargs__', - '__reduce_ex__', '__reduce__') - if not any(m in member_type.__dict__ for m in methods): - _make_class_unpicklable(enum_class) - - # instantiate them, checking for duplicates as we go - # we instantiate first instead of checking for duplicates first in case - # a custom __new__ is doing something funky with the values -- such as - # auto-numbering ;) - for member_name in classdict._member_names: - value = enum_members[member_name] - if not isinstance(value, tuple): - args = (value, ) - else: - args = value - if member_type is tuple: # special case for tuple enums - args = (args, ) # wrap it one more time - if not use_args: - enum_member = __new__(enum_class) - if not hasattr(enum_member, '_value_'): - enum_member._value_ = value - else: - enum_member = __new__(enum_class, *args) - if not hasattr(enum_member, '_value_'): - if member_type is object: - enum_member._value_ = value - else: - enum_member._value_ = member_type(*args) - value = enum_member._value_ - enum_member._name_ = member_name - enum_member.__objclass__ = enum_class - enum_member.__init__(*args) - # If another member with the same value was already defined, the - # new member becomes an alias to the existing one. - for name, canonical_member in enum_class._member_map_.items(): - if canonical_member._value_ == enum_member._value_: - enum_member = canonical_member - break - else: - # Aliases don't appear in member names (only in __members__). - enum_class._member_names_.append(member_name) - # performance boost for any member that would not shadow - # a DynamicClassAttribute - if member_name not in dynamic_attributes: - setattr(enum_class, member_name, enum_member) - # now add to _member_map_ - enum_class._member_map_[member_name] = enum_member - try: - # This may fail if value is not hashable. We can't add the value - # to the map, and by-value lookups for this value will be - # linear. - enum_class._value2member_map_[value] = enum_member - except TypeError: - pass - - # double check that repr and friends are not the mixin's or various - # things break (such as pickle) - for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): - class_method = getattr(enum_class, name) - obj_method = getattr(member_type, name, None) - enum_method = getattr(first_enum, name, None) - if obj_method is not None and obj_method is class_method: - setattr(enum_class, name, enum_method) - - # replace any other __new__ with our own (as long as Enum is not None, - # anyway) -- again, this is to support pickle - if Enum is not None: - # if the user defined their own __new__, save it before it gets - # clobbered in case they subclass later - if save_new: - enum_class.__new_member__ = __new__ - enum_class.__new__ = Enum.__new__ - - # py3 support for definition order (helps keep py2/py3 code in sync) - if _order_ is not None: - if isinstance(_order_, str): - _order_ = _order_.replace(',', ' ').split() - if _order_ != enum_class._member_names_: - raise TypeError('member order does not match _order_') - - return enum_class - - def __bool__(self): - """ - classes/types should always be True. - """ - return True - - def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): - """Either returns an existing member, or creates a new enum class. - - This method is used both when an enum class is given a value to match - to an enumeration member (i.e. Color(3)) and for the functional API - (i.e. Color = Enum('Color', names='RED GREEN BLUE')). - - When used for the functional API: - - `value` will be the name of the new class. - - `names` should be either a string of white-space/comma delimited names - (values will start at `start`), or an iterator/mapping of name, value pairs. - - `module` should be set to the module this class is being created in; - if it is not set, an attempt to find that module will be made, but if - it fails the class will not be picklable. - - `qualname` should be set to the actual location this class can be found - at in its module; by default it is set to the global scope. If this is - not correct, unpickling will fail in some circumstances. - - `type`, if set, will be mixed in as the first base class. - - """ - if names is None: # simple value lookup - return cls.__new__(cls, value) - # otherwise, functional API: we're creating a new Enum type - return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start) - - def __contains__(cls, member): - if not isinstance(member, Enum): - import warnings - warnings.warn( - "using non-Enums in containment checks will raise " - "TypeError in Python 3.8", - DeprecationWarning, 2) - return isinstance(member, cls) and member._name_ in cls._member_map_ - - def __delattr__(cls, attr): - # nicer error message when someone tries to delete an attribute - # (see issue19025). - if attr in cls._member_map_: - raise AttributeError( - "%s: cannot delete Enum member." % cls.__name__) - super().__delattr__(attr) - - def __dir__(self): - return (['__class__', '__doc__', '__members__', '__module__'] + - self._member_names_) - - def __getattr__(cls, name): - """Return the enum member matching `name` - - We use __getattr__ instead of descriptors or inserting into the enum - class' __dict__ in order to support `name` and `value` being both - properties for enum members (which live in the class' __dict__) and - enum members themselves. - - """ - if _is_dunder(name): - raise AttributeError(name) - try: - return cls._member_map_[name] - except KeyError: - raise AttributeError(name) from None - - def __getitem__(cls, name): - return cls._member_map_[name] - - def __iter__(cls): - return (cls._member_map_[name] for name in cls._member_names_) - - def __len__(cls): - return len(cls._member_names_) - - @property - def __members__(cls): - """Returns a mapping of member name->value. - - This mapping lists all enum members, including aliases. Note that this - is a read-only view of the internal mapping. - - """ - return MappingProxyType(cls._member_map_) - - def __repr__(cls): - return "" % cls.__name__ - - def __reversed__(cls): - return (cls._member_map_[name] for name in reversed(cls._member_names_)) - - def __setattr__(cls, name, value): - """Block attempts to reassign Enum members. - - A simple assignment to the class namespace only changes one of the - several possible ways to get an Enum member from the Enum class, - resulting in an inconsistent Enumeration. - - """ - member_map = cls.__dict__.get('_member_map_', {}) - if name in member_map: - raise AttributeError('Cannot reassign members.') - super().__setattr__(name, value) - - def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): - """Convenience method to create a new Enum class. - - `names` can be: - - * A string containing member names, separated either with spaces or - commas. Values are incremented by 1 from `start`. - * An iterable of member names. Values are incremented by 1 from `start`. - * An iterable of (member name, value) pairs. - * A mapping of member name -> value pairs. - - """ - metacls = cls.__class__ - bases = (cls, ) if type is None else (type, cls) - _, first_enum = cls._get_mixins_(bases) - classdict = metacls.__prepare__(class_name, bases) - - # special processing needed for names? - if isinstance(names, str): - names = names.replace(',', ' ').split() - if isinstance(names, (tuple, list)) and names and isinstance(names[0], str): - original_names, names = names, [] - last_values = [] - for count, name in enumerate(original_names): - value = first_enum._generate_next_value_(name, start, count, last_values[:]) - last_values.append(value) - names.append((name, value)) - - # Here, names is either an iterable of (name, value) or a mapping. - for item in names: - if isinstance(item, str): - member_name, member_value = item, names[item] - else: - member_name, member_value = item - classdict[member_name] = member_value - enum_class = metacls.__new__(metacls, class_name, bases, classdict) - - # TODO: replace the frame hack if a blessed way to know the calling - # module is ever developed - if module is None: - try: - module = sys._getframe(2).f_globals['__name__'] - except (AttributeError, ValueError, KeyError) as exc: - pass - if module is None: - _make_class_unpicklable(enum_class) - else: - enum_class.__module__ = module - if qualname is not None: - enum_class.__qualname__ = qualname - - return enum_class - - @staticmethod - def _get_mixins_(bases): - """Returns the type for creating enum members, and the first inherited - enum class. - - bases: the tuple of bases that was given to __new__ - - """ - if not bases: - return object, Enum - - def _find_data_type(bases): - for chain in bases: - for base in chain.__mro__: - if base is object: - continue - elif '__new__' in base.__dict__: - if issubclass(base, Enum): - continue - return base - - # ensure final parent class is an Enum derivative, find any concrete - # data type, and check that Enum has no members - first_enum = bases[-1] - if not issubclass(first_enum, Enum): - raise TypeError("new enumerations should be created as " - "`EnumName([mixin_type, ...] [data_type,] enum_type)`") - member_type = _find_data_type(bases) or object - if first_enum._member_names_: - raise TypeError("Cannot extend enumerations") - return member_type, first_enum - - @staticmethod - def _find_new_(classdict, member_type, first_enum): - """Returns the __new__ to be used for creating the enum members. - - classdict: the class dictionary given to __new__ - member_type: the data type whose __new__ will be used by default - first_enum: enumeration to check for an overriding __new__ - - """ - # now find the correct __new__, checking to see of one was defined - # by the user; also check earlier enum classes in case a __new__ was - # saved as __new_member__ - __new__ = classdict.get('__new__', None) - - # should __new__ be saved as __new_member__ later? - save_new = __new__ is not None - - if __new__ is None: - # check all possibles for __new_member__ before falling back to - # __new__ - for method in ('__new_member__', '__new__'): - for possible in (member_type, first_enum): - target = getattr(possible, method, None) - if target not in { - None, - None.__new__, - object.__new__, - Enum.__new__, - }: - __new__ = target - break - if __new__ is not None: - break - else: - __new__ = object.__new__ - - # if a non-object.__new__ is used then whatever value/tuple was - # assigned to the enum member name will be passed to __new__ and to the - # new enum member's __init__ - if __new__ is object.__new__: - use_args = False - else: - use_args = True - return __new__, save_new, use_args - - -class Enum(metaclass=EnumMeta): - """Generic enumeration. - - Derive from this class to define new enumerations. - - """ - def __new__(cls, value): - # all enum instances are actually created during class construction - # without calling this method; this method is called by the metaclass' - # __call__ (i.e. Color(3) ), and by pickle - if type(value) is cls: - # For lookups like Color(Color.RED) - return value - # by-value search for a matching enum member - # see if it's in the reverse mapping (for hashable values) - try: - return cls._value2member_map_[value] - except KeyError: - # Not found, no need to do long O(n) search - pass - except TypeError: - # not there, now do long search -- O(n) behavior - for member in cls._member_map_.values(): - if member._value_ == value: - return member - # still not found -- try _missing_ hook - try: - exc = None - result = cls._missing_(value) - except Exception as e: - exc = e - result = None - if isinstance(result, cls): - return result - else: - ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__)) - if result is None and exc is None: - raise ve_exc - elif exc is None: - exc = TypeError( - 'error in %s._missing_: returned %r instead of None or a valid member' - % (cls.__name__, result) - ) - exc.__context__ = ve_exc - raise exc - - def _generate_next_value_(name, start, count, last_values): - for last_value in reversed(last_values): - try: - return last_value + 1 - except TypeError: - pass - else: - return start - - @classmethod - def _missing_(cls, value): - raise ValueError("%r is not a valid %s" % (value, cls.__name__)) - - def __repr__(self): - return "<%s.%s: %r>" % ( - self.__class__.__name__, self._name_, self._value_) - - def __str__(self): - return "%s.%s" % (self.__class__.__name__, self._name_) - - def __dir__(self): - added_behavior = [ - m - for cls in self.__class__.mro() - for m in cls.__dict__ - if m[0] != '_' and m not in self._member_map_ - ] - return (['__class__', '__doc__', '__module__'] + added_behavior) - - def __format__(self, format_spec): - # mixed-in Enums should use the mixed-in type's __format__, otherwise - # we can get strange results with the Enum name showing up instead of - # the value - - # pure Enum branch - if self._member_type_ is object: - cls = str - val = str(self) - # mix-in branch - else: - cls = self._member_type_ - val = self._value_ - return cls.__format__(val, format_spec) - - def __hash__(self): - return hash(self._name_) - - def __reduce_ex__(self, proto): - return self.__class__, (self._value_, ) - - # DynamicClassAttribute is used to provide access to the `name` and - # `value` properties of enum members while keeping some measure of - # protection from modification, while still allowing for an enumeration - # to have members named `name` and `value`. This works because enumeration - # members are not set directly on the enum class -- __getattr__ is - # used to look them up. - - @DynamicClassAttribute - def name(self): - """The name of the Enum member.""" - return self._name_ - - @DynamicClassAttribute - def value(self): - """The value of the Enum member.""" - return self._value_ - - @classmethod - def _convert(cls, name, module, filter, source=None): - """ - Create a new Enum subclass that replaces a collection of global constants - """ - # convert all constants from source (or module) that pass filter() to - # a new Enum called name, and export the enum and its members back to - # module; - # also, replace the __reduce_ex__ method so unpickling works in - # previous Python versions - module_globals = vars(sys.modules[module]) - if source: - source = vars(source) - else: - source = module_globals - # We use an OrderedDict of sorted source keys so that the - # _value2member_map is populated in the same order every time - # for a consistent reverse mapping of number to name when there - # are multiple names for the same number rather than varying - # between runs due to hash randomization of the module dictionary. - members = [ - (name, source[name]) - for name in source.keys() - if filter(name)] - try: - # sort by value - members.sort(key=lambda t: (t[1], t[0])) - except TypeError: - # unless some values aren't comparable, in which case sort by name - members.sort(key=lambda t: t[0]) - cls = cls(name, members, module=module) - cls.__reduce_ex__ = _reduce_ex_by_name - module_globals.update(cls.__members__) - module_globals[name] = cls - return cls - - -class IntEnum(int, Enum): - """Enum where members are also (and must be) ints""" - - -def _reduce_ex_by_name(self, proto): - return self.name - -class Flag(Enum): - """Support for flags""" - - def _generate_next_value_(name, start, count, last_values): - """ - Generate the next value when not given. - - name: the name of the member - start: the initial start value or None - count: the number of existing members - last_value: the last value assigned or None - """ - if not count: - return start if start is not None else 1 - for last_value in reversed(last_values): - try: - high_bit = _high_bit(last_value) - break - except Exception: - raise TypeError('Invalid Flag value: %r' % last_value) from None - return 2 ** (high_bit+1) - - @classmethod - def _missing_(cls, value): - original_value = value - if value < 0: - value = ~value - possible_member = cls._create_pseudo_member_(value) - if original_value < 0: - possible_member = ~possible_member - return possible_member - - @classmethod - def _create_pseudo_member_(cls, value): - """ - Create a composite member iff value contains only members. - """ - pseudo_member = cls._value2member_map_.get(value, None) - if pseudo_member is None: - # verify all bits are accounted for - _, extra_flags = _decompose(cls, value) - if extra_flags: - raise ValueError("%r is not a valid %s" % (value, cls.__name__)) - # construct a singleton enum pseudo-member - pseudo_member = object.__new__(cls) - pseudo_member._name_ = None - pseudo_member._value_ = value - # use setdefault in case another thread already created a composite - # with this value - pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) - return pseudo_member - - def __contains__(self, other): - if not isinstance(other, self.__class__): - import warnings - warnings.warn( - "using non-Flags in containment checks will raise " - "TypeError in Python 3.8", - DeprecationWarning, 2) - return False - return other._value_ & self._value_ == other._value_ - - def __repr__(self): - cls = self.__class__ - if self._name_ is not None: - return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_) - members, uncovered = _decompose(cls, self._value_) - return '<%s.%s: %r>' % ( - cls.__name__, - '|'.join([str(m._name_ or m._value_) for m in members]), - self._value_, - ) - - def __str__(self): - cls = self.__class__ - if self._name_ is not None: - return '%s.%s' % (cls.__name__, self._name_) - members, uncovered = _decompose(cls, self._value_) - if len(members) == 1 and members[0]._name_ is None: - return '%s.%r' % (cls.__name__, members[0]._value_) - else: - return '%s.%s' % ( - cls.__name__, - '|'.join([str(m._name_ or m._value_) for m in members]), - ) - - def __bool__(self): - return bool(self._value_) - - def __or__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.__class__(self._value_ | other._value_) - - def __and__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.__class__(self._value_ & other._value_) - - def __xor__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.__class__(self._value_ ^ other._value_) - - def __invert__(self): - members, uncovered = _decompose(self.__class__, self._value_) - inverted = self.__class__(0) - for m in self.__class__: - if m not in members and not (m._value_ & self._value_): - inverted = inverted | m - return self.__class__(inverted) - - -class IntFlag(int, Flag): - """Support for integer-based Flags""" - - @classmethod - def _missing_(cls, value): - if not isinstance(value, int): - raise ValueError("%r is not a valid %s" % (value, cls.__name__)) - new_member = cls._create_pseudo_member_(value) - return new_member - - @classmethod - def _create_pseudo_member_(cls, value): - pseudo_member = cls._value2member_map_.get(value, None) - if pseudo_member is None: - need_to_create = [value] - # get unaccounted for bits - _, extra_flags = _decompose(cls, value) - # timer = 10 - while extra_flags: - # timer -= 1 - bit = _high_bit(extra_flags) - flag_value = 2 ** bit - if (flag_value not in cls._value2member_map_ and - flag_value not in need_to_create - ): - need_to_create.append(flag_value) - if extra_flags == -flag_value: - extra_flags = 0 - else: - extra_flags ^= flag_value - for value in reversed(need_to_create): - # construct singleton pseudo-members - pseudo_member = int.__new__(cls, value) - pseudo_member._name_ = None - pseudo_member._value_ = value - # use setdefault in case another thread already created a composite - # with this value - pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) - return pseudo_member - - def __or__(self, other): - if not isinstance(other, (self.__class__, int)): - return NotImplemented - result = self.__class__(self._value_ | self.__class__(other)._value_) - return result - - def __and__(self, other): - if not isinstance(other, (self.__class__, int)): - return NotImplemented - return self.__class__(self._value_ & self.__class__(other)._value_) - - def __xor__(self, other): - if not isinstance(other, (self.__class__, int)): - return NotImplemented - return self.__class__(self._value_ ^ self.__class__(other)._value_) - - __ror__ = __or__ - __rand__ = __and__ - __rxor__ = __xor__ - - def __invert__(self): - result = self.__class__(~self._value_) - return result - - -def _high_bit(value): - """returns index of highest bit, or -1 if value is zero or negative""" - return value.bit_length() - 1 - -def unique(enumeration): - """Class decorator for enumerations ensuring unique member values.""" - duplicates = [] - for name, member in enumeration.__members__.items(): - if name != member.name: - duplicates.append((name, member.name)) - if duplicates: - alias_details = ', '.join( - ["%s -> %s" % (alias, name) for (alias, name) in duplicates]) - raise ValueError('duplicate values found in %r: %s' % - (enumeration, alias_details)) - return enumeration - -def _decompose(flag, value): - """Extract all members from the value.""" - # _decompose is only called if the value is not named - not_covered = value - negative = value < 0 - # issue29167: wrap accesses to _value2member_map_ in a list to avoid race - # conditions between iterating over it and having more pseudo- - # members added to it - if negative: - # only check for named flags - flags_to_check = [ - (m, v) - for v, m in list(flag._value2member_map_.items()) - if m.name is not None - ] - else: - # check for named flags and powers-of-two flags - flags_to_check = [ - (m, v) - for v, m in list(flag._value2member_map_.items()) - if m.name is not None or _power_of_two(v) - ] - members = [] - for member, member_value in flags_to_check: - if member_value and member_value & value == member_value: - members.append(member) - not_covered &= ~member_value - if not members and value in flag._value2member_map_: - members.append(flag._value2member_map_[value]) - members.sort(key=lambda m: m._value_, reverse=True) - if len(members) > 1 and members[0].value == value: - # we have the breakdown, don't need the value member itself - members.pop(0) - return members, not_covered - -def _power_of_two(value): - if value < 1: - return False - return value == 2 ** _high_bit(value) diff --git a/experiment/simulation/backend/venv/lib/python3.7/fnmatch.py b/experiment/simulation/backend/venv/lib/python3.7/fnmatch.py deleted file mode 100644 index b98e641..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/fnmatch.py +++ /dev/null @@ -1,128 +0,0 @@ -"""Filename matching with shell patterns. - -fnmatch(FILENAME, PATTERN) matches according to the local convention. -fnmatchcase(FILENAME, PATTERN) always takes case in account. - -The functions operate by translating the pattern into a regular -expression. They cache the compiled regular expressions for speed. - -The function translate(PATTERN) returns a regular expression -corresponding to PATTERN. (It does not compile it.) -""" -import os -import posixpath -import re -import functools - -__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] - -def fnmatch(name, pat): - """Test whether FILENAME matches PATTERN. - - Patterns are Unix shell style: - - * matches everything - ? matches any single character - [seq] matches any character in seq - [!seq] matches any char not in seq - - An initial period in FILENAME is not special. - Both FILENAME and PATTERN are first case-normalized - if the operating system requires it. - If you don't want this, use fnmatchcase(FILENAME, PATTERN). - """ - name = os.path.normcase(name) - pat = os.path.normcase(pat) - return fnmatchcase(name, pat) - -@functools.lru_cache(maxsize=256, typed=True) -def _compile_pattern(pat): - if isinstance(pat, bytes): - pat_str = str(pat, 'ISO-8859-1') - res_str = translate(pat_str) - res = bytes(res_str, 'ISO-8859-1') - else: - res = translate(pat) - return re.compile(res).match - -def filter(names, pat): - """Return the subset of the list NAMES that match PAT.""" - result = [] - pat = os.path.normcase(pat) - match = _compile_pattern(pat) - if os.path is posixpath: - # normcase on posix is NOP. Optimize it away from the loop. - for name in names: - if match(name): - result.append(name) - else: - for name in names: - if match(os.path.normcase(name)): - result.append(name) - return result - -def fnmatchcase(name, pat): - """Test whether FILENAME matches PATTERN, including case. - - This is a version of fnmatch() which doesn't case-normalize - its arguments. - """ - match = _compile_pattern(pat) - return match(name) is not None - - -def translate(pat): - """Translate a shell PATTERN to a regular expression. - - There is no way to quote meta-characters. - """ - - i, n = 0, len(pat) - res = '' - while i < n: - c = pat[i] - i = i+1 - if c == '*': - res = res + '.*' - elif c == '?': - res = res + '.' - elif c == '[': - j = i - if j < n and pat[j] == '!': - j = j+1 - if j < n and pat[j] == ']': - j = j+1 - while j < n and pat[j] != ']': - j = j+1 - if j >= n: - res = res + '\\[' - else: - stuff = pat[i:j] - if '--' not in stuff: - stuff = stuff.replace('\\', r'\\') - else: - chunks = [] - k = i+2 if pat[i] == '!' else i+1 - while True: - k = pat.find('-', k, j) - if k < 0: - break - chunks.append(pat[i:k]) - i = k+1 - k = k+3 - chunks.append(pat[i:j]) - # Escape backslashes and hyphens for set difference (--). - # Hyphens that create ranges shouldn't be escaped. - stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-') - for s in chunks) - # Escape set operations (&&, ~~ and ||). - stuff = re.sub(r'([&~|])', r'\\\1', stuff) - i = j+1 - if stuff[0] == '!': - stuff = '^' + stuff[1:] - elif stuff[0] in ('^', '['): - stuff = '\\' + stuff - res = '%s[%s]' % (res, stuff) - else: - res = res + re.escape(c) - return r'(?s:%s)\Z' % res diff --git a/experiment/simulation/backend/venv/lib/python3.7/functools.py b/experiment/simulation/backend/venv/lib/python3.7/functools.py deleted file mode 100644 index badaa82..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/functools.py +++ /dev/null @@ -1,849 +0,0 @@ -"""functools.py - Tools for working with functions and callable objects -""" -# Python module wrapper for _functools C module -# to allow utilities written in Python to be added -# to the functools module. -# Written by Nick Coghlan , -# Raymond Hettinger , -# and Łukasz Langa . -# Copyright (C) 2006-2013 Python Software Foundation. -# See C source code for _functools credits/copyright - -__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', - 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial', - 'partialmethod', 'singledispatch'] - -try: - from _functools import reduce -except ImportError: - pass -from abc import get_cache_token -from collections import namedtuple -# import types, weakref # Deferred to single_dispatch() -from reprlib import recursive_repr -from _thread import RLock - - -################################################################################ -### update_wrapper() and wraps() decorator -################################################################################ - -# update_wrapper() and wraps() are tools to help write -# wrapper functions that can handle naive introspection - -WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__', - '__annotations__') -WRAPPER_UPDATES = ('__dict__',) -def update_wrapper(wrapper, - wrapped, - assigned = WRAPPER_ASSIGNMENTS, - updated = WRAPPER_UPDATES): - """Update a wrapper function to look like the wrapped function - - wrapper is the function to be updated - wrapped is the original function - assigned is a tuple naming the attributes assigned directly - from the wrapped function to the wrapper function (defaults to - functools.WRAPPER_ASSIGNMENTS) - updated is a tuple naming the attributes of the wrapper that - are updated with the corresponding attribute from the wrapped - function (defaults to functools.WRAPPER_UPDATES) - """ - for attr in assigned: - try: - value = getattr(wrapped, attr) - except AttributeError: - pass - else: - setattr(wrapper, attr, value) - for attr in updated: - getattr(wrapper, attr).update(getattr(wrapped, attr, {})) - # Issue #17482: set __wrapped__ last so we don't inadvertently copy it - # from the wrapped function when updating __dict__ - wrapper.__wrapped__ = wrapped - # Return the wrapper so this can be used as a decorator via partial() - return wrapper - -def wraps(wrapped, - assigned = WRAPPER_ASSIGNMENTS, - updated = WRAPPER_UPDATES): - """Decorator factory to apply update_wrapper() to a wrapper function - - Returns a decorator that invokes update_wrapper() with the decorated - function as the wrapper argument and the arguments to wraps() as the - remaining arguments. Default arguments are as for update_wrapper(). - This is a convenience function to simplify applying partial() to - update_wrapper(). - """ - return partial(update_wrapper, wrapped=wrapped, - assigned=assigned, updated=updated) - - -################################################################################ -### total_ordering class decorator -################################################################################ - -# The total ordering functions all invoke the root magic method directly -# rather than using the corresponding operator. This avoids possible -# infinite recursion that could occur when the operator dispatch logic -# detects a NotImplemented result and then calls a reflected method. - -def _gt_from_lt(self, other, NotImplemented=NotImplemented): - 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).' - op_result = self.__lt__(other) - if op_result is NotImplemented: - return op_result - return not op_result and self != other - -def _le_from_lt(self, other, NotImplemented=NotImplemented): - 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).' - op_result = self.__lt__(other) - return op_result or self == other - -def _ge_from_lt(self, other, NotImplemented=NotImplemented): - 'Return a >= b. Computed by @total_ordering from (not a < b).' - op_result = self.__lt__(other) - if op_result is NotImplemented: - return op_result - return not op_result - -def _ge_from_le(self, other, NotImplemented=NotImplemented): - 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).' - op_result = self.__le__(other) - if op_result is NotImplemented: - return op_result - return not op_result or self == other - -def _lt_from_le(self, other, NotImplemented=NotImplemented): - 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).' - op_result = self.__le__(other) - if op_result is NotImplemented: - return op_result - return op_result and self != other - -def _gt_from_le(self, other, NotImplemented=NotImplemented): - 'Return a > b. Computed by @total_ordering from (not a <= b).' - op_result = self.__le__(other) - if op_result is NotImplemented: - return op_result - return not op_result - -def _lt_from_gt(self, other, NotImplemented=NotImplemented): - 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).' - op_result = self.__gt__(other) - if op_result is NotImplemented: - return op_result - return not op_result and self != other - -def _ge_from_gt(self, other, NotImplemented=NotImplemented): - 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).' - op_result = self.__gt__(other) - return op_result or self == other - -def _le_from_gt(self, other, NotImplemented=NotImplemented): - 'Return a <= b. Computed by @total_ordering from (not a > b).' - op_result = self.__gt__(other) - if op_result is NotImplemented: - return op_result - return not op_result - -def _le_from_ge(self, other, NotImplemented=NotImplemented): - 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).' - op_result = self.__ge__(other) - if op_result is NotImplemented: - return op_result - return not op_result or self == other - -def _gt_from_ge(self, other, NotImplemented=NotImplemented): - 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).' - op_result = self.__ge__(other) - if op_result is NotImplemented: - return op_result - return op_result and self != other - -def _lt_from_ge(self, other, NotImplemented=NotImplemented): - 'Return a < b. Computed by @total_ordering from (not a >= b).' - op_result = self.__ge__(other) - if op_result is NotImplemented: - return op_result - return not op_result - -_convert = { - '__lt__': [('__gt__', _gt_from_lt), - ('__le__', _le_from_lt), - ('__ge__', _ge_from_lt)], - '__le__': [('__ge__', _ge_from_le), - ('__lt__', _lt_from_le), - ('__gt__', _gt_from_le)], - '__gt__': [('__lt__', _lt_from_gt), - ('__ge__', _ge_from_gt), - ('__le__', _le_from_gt)], - '__ge__': [('__le__', _le_from_ge), - ('__gt__', _gt_from_ge), - ('__lt__', _lt_from_ge)] -} - -def total_ordering(cls): - """Class decorator that fills in missing ordering methods""" - # Find user-defined comparisons (not those inherited from object). - roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)} - if not roots: - raise ValueError('must define at least one ordering operation: < > <= >=') - root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ - for opname, opfunc in _convert[root]: - if opname not in roots: - opfunc.__name__ = opname - setattr(cls, opname, opfunc) - return cls - - -################################################################################ -### cmp_to_key() function converter -################################################################################ - -def cmp_to_key(mycmp): - """Convert a cmp= function into a key= function""" - class K(object): - __slots__ = ['obj'] - def __init__(self, obj): - self.obj = obj - def __lt__(self, other): - return mycmp(self.obj, other.obj) < 0 - def __gt__(self, other): - return mycmp(self.obj, other.obj) > 0 - def __eq__(self, other): - return mycmp(self.obj, other.obj) == 0 - def __le__(self, other): - return mycmp(self.obj, other.obj) <= 0 - def __ge__(self, other): - return mycmp(self.obj, other.obj) >= 0 - __hash__ = None - return K - -try: - from _functools import cmp_to_key -except ImportError: - pass - - -################################################################################ -### partial() argument application -################################################################################ - -# Purely functional, no descriptor behaviour -class partial: - """New function with partial application of the given arguments - and keywords. - """ - - __slots__ = "func", "args", "keywords", "__dict__", "__weakref__" - - def __new__(*args, **keywords): - if not args: - raise TypeError("descriptor '__new__' of partial needs an argument") - if len(args) < 2: - raise TypeError("type 'partial' takes at least one argument") - cls, func, *args = args - if not callable(func): - raise TypeError("the first argument must be callable") - args = tuple(args) - - if hasattr(func, "func"): - args = func.args + args - tmpkw = func.keywords.copy() - tmpkw.update(keywords) - keywords = tmpkw - del tmpkw - func = func.func - - self = super(partial, cls).__new__(cls) - - self.func = func - self.args = args - self.keywords = keywords - return self - - def __call__(*args, **keywords): - if not args: - raise TypeError("descriptor '__call__' of partial needs an argument") - self, *args = args - newkeywords = self.keywords.copy() - newkeywords.update(keywords) - return self.func(*self.args, *args, **newkeywords) - - @recursive_repr() - def __repr__(self): - qualname = type(self).__qualname__ - args = [repr(self.func)] - args.extend(repr(x) for x in self.args) - args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items()) - if type(self).__module__ == "functools": - return f"functools.{qualname}({', '.join(args)})" - return f"{qualname}({', '.join(args)})" - - def __reduce__(self): - return type(self), (self.func,), (self.func, self.args, - self.keywords or None, self.__dict__ or None) - - def __setstate__(self, state): - if not isinstance(state, tuple): - raise TypeError("argument to __setstate__ must be a tuple") - if len(state) != 4: - raise TypeError(f"expected 4 items in state, got {len(state)}") - func, args, kwds, namespace = state - if (not callable(func) or not isinstance(args, tuple) or - (kwds is not None and not isinstance(kwds, dict)) or - (namespace is not None and not isinstance(namespace, dict))): - raise TypeError("invalid partial state") - - args = tuple(args) # just in case it's a subclass - if kwds is None: - kwds = {} - elif type(kwds) is not dict: # XXX does it need to be *exactly* dict? - kwds = dict(kwds) - if namespace is None: - namespace = {} - - self.__dict__ = namespace - self.func = func - self.args = args - self.keywords = kwds - -try: - from _functools import partial -except ImportError: - pass - -# Descriptor version -class partialmethod(object): - """Method descriptor with partial application of the given arguments - and keywords. - - Supports wrapping existing descriptors and handles non-descriptor - callables as instance methods. - """ - - def __init__(*args, **keywords): - if len(args) >= 2: - self, func, *args = args - elif not args: - raise TypeError("descriptor '__init__' of partialmethod " - "needs an argument") - elif 'func' in keywords: - func = keywords.pop('func') - self, *args = args - else: - raise TypeError("type 'partialmethod' takes at least one argument, " - "got %d" % (len(args)-1)) - args = tuple(args) - - if not callable(func) and not hasattr(func, "__get__"): - raise TypeError("{!r} is not callable or a descriptor" - .format(func)) - - # func could be a descriptor like classmethod which isn't callable, - # so we can't inherit from partial (it verifies func is callable) - if isinstance(func, partialmethod): - # flattening is mandatory in order to place cls/self before all - # other arguments - # it's also more efficient since only one function will be called - self.func = func.func - self.args = func.args + args - self.keywords = func.keywords.copy() - self.keywords.update(keywords) - else: - self.func = func - self.args = args - self.keywords = keywords - - def __repr__(self): - args = ", ".join(map(repr, self.args)) - keywords = ", ".join("{}={!r}".format(k, v) - for k, v in self.keywords.items()) - format_string = "{module}.{cls}({func}, {args}, {keywords})" - return format_string.format(module=self.__class__.__module__, - cls=self.__class__.__qualname__, - func=self.func, - args=args, - keywords=keywords) - - def _make_unbound_method(self): - def _method(*args, **keywords): - call_keywords = self.keywords.copy() - call_keywords.update(keywords) - cls_or_self, *rest = args - call_args = (cls_or_self,) + self.args + tuple(rest) - return self.func(*call_args, **call_keywords) - _method.__isabstractmethod__ = self.__isabstractmethod__ - _method._partialmethod = self - return _method - - def __get__(self, obj, cls): - get = getattr(self.func, "__get__", None) - result = None - if get is not None: - new_func = get(obj, cls) - if new_func is not self.func: - # Assume __get__ returning something new indicates the - # creation of an appropriate callable - result = partial(new_func, *self.args, **self.keywords) - try: - result.__self__ = new_func.__self__ - except AttributeError: - pass - if result is None: - # If the underlying descriptor didn't do anything, treat this - # like an instance method - result = self._make_unbound_method().__get__(obj, cls) - return result - - @property - def __isabstractmethod__(self): - return getattr(self.func, "__isabstractmethod__", False) - - -################################################################################ -### LRU Cache function decorator -################################################################################ - -_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"]) - -class _HashedSeq(list): - """ This class guarantees that hash() will be called no more than once - per element. This is important because the lru_cache() will hash - the key multiple times on a cache miss. - - """ - - __slots__ = 'hashvalue' - - def __init__(self, tup, hash=hash): - self[:] = tup - self.hashvalue = hash(tup) - - def __hash__(self): - return self.hashvalue - -def _make_key(args, kwds, typed, - kwd_mark = (object(),), - fasttypes = {int, str}, - tuple=tuple, type=type, len=len): - """Make a cache key from optionally typed positional and keyword arguments - - The key is constructed in a way that is flat as possible rather than - as a nested structure that would take more memory. - - If there is only a single argument and its data type is known to cache - its hash value, then that argument is returned without a wrapper. This - saves space and improves lookup speed. - - """ - # All of code below relies on kwds preserving the order input by the user. - # Formerly, we sorted() the kwds before looping. The new way is *much* - # faster; however, it means that f(x=1, y=2) will now be treated as a - # distinct call from f(y=2, x=1) which will be cached separately. - key = args - if kwds: - key += kwd_mark - for item in kwds.items(): - key += item - if typed: - key += tuple(type(v) for v in args) - if kwds: - key += tuple(type(v) for v in kwds.values()) - elif len(key) == 1 and type(key[0]) in fasttypes: - return key[0] - return _HashedSeq(key) - -def lru_cache(maxsize=128, typed=False): - """Least-recently-used cache decorator. - - If *maxsize* is set to None, the LRU features are disabled and the cache - can grow without bound. - - If *typed* is True, arguments of different types will be cached separately. - For example, f(3.0) and f(3) will be treated as distinct calls with - distinct results. - - Arguments to the cached function must be hashable. - - View the cache statistics named tuple (hits, misses, maxsize, currsize) - with f.cache_info(). Clear the cache and statistics with f.cache_clear(). - Access the underlying function with f.__wrapped__. - - See: http://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU) - - """ - - # Users should only access the lru_cache through its public API: - # cache_info, cache_clear, and f.__wrapped__ - # The internals of the lru_cache are encapsulated for thread safety and - # to allow the implementation to change (including a possible C version). - - # Early detection of an erroneous call to @lru_cache without any arguments - # resulting in the inner function being passed to maxsize instead of an - # integer or None. Negative maxsize is treated as 0. - if isinstance(maxsize, int): - if maxsize < 0: - maxsize = 0 - elif maxsize is not None: - raise TypeError('Expected maxsize to be an integer or None') - - def decorating_function(user_function): - wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) - return update_wrapper(wrapper, user_function) - - return decorating_function - -def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): - # Constants shared by all lru cache instances: - sentinel = object() # unique object used to signal cache misses - make_key = _make_key # build a key from the function arguments - PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields - - cache = {} - hits = misses = 0 - full = False - cache_get = cache.get # bound method to lookup a key or return None - cache_len = cache.__len__ # get cache size without calling len() - lock = RLock() # because linkedlist updates aren't threadsafe - root = [] # root of the circular doubly linked list - root[:] = [root, root, None, None] # initialize by pointing to self - - if maxsize == 0: - - def wrapper(*args, **kwds): - # No caching -- just a statistics update - nonlocal misses - misses += 1 - result = user_function(*args, **kwds) - return result - - elif maxsize is None: - - def wrapper(*args, **kwds): - # Simple caching without ordering or size limit - nonlocal hits, misses - key = make_key(args, kwds, typed) - result = cache_get(key, sentinel) - if result is not sentinel: - hits += 1 - return result - misses += 1 - result = user_function(*args, **kwds) - cache[key] = result - return result - - else: - - def wrapper(*args, **kwds): - # Size limited caching that tracks accesses by recency - nonlocal root, hits, misses, full - key = make_key(args, kwds, typed) - with lock: - link = cache_get(key) - if link is not None: - # Move the link to the front of the circular queue - link_prev, link_next, _key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - hits += 1 - return result - misses += 1 - result = user_function(*args, **kwds) - with lock: - if key in cache: - # Getting here means that this same key was added to the - # cache while the lock was released. Since the link - # update is already done, we need only return the - # computed result and update the count of misses. - pass - elif full: - # Use the old root to store the new key and result. - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - # Empty the oldest link and make it the new root. - # Keep a reference to the old key and old result to - # prevent their ref counts from going to zero during the - # update. That will prevent potentially arbitrary object - # clean-up code (i.e. __del__) from running while we're - # still adjusting the links. - root = oldroot[NEXT] - oldkey = root[KEY] - oldresult = root[RESULT] - root[KEY] = root[RESULT] = None - # Now update the cache dictionary. - del cache[oldkey] - # Save the potentially reentrant cache[key] assignment - # for last, after the root and links have been put in - # a consistent state. - cache[key] = oldroot - else: - # Put result in a new link at the front of the queue. - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - # Use the cache_len bound method instead of the len() function - # which could potentially be wrapped in an lru_cache itself. - full = (cache_len() >= maxsize) - return result - - def cache_info(): - """Report cache statistics""" - with lock: - return _CacheInfo(hits, misses, maxsize, cache_len()) - - def cache_clear(): - """Clear the cache and cache statistics""" - nonlocal hits, misses, full - with lock: - cache.clear() - root[:] = [root, root, None, None] - hits = misses = 0 - full = False - - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return wrapper - -try: - from _functools import _lru_cache_wrapper -except ImportError: - pass - - -################################################################################ -### singledispatch() - single-dispatch generic function decorator -################################################################################ - -def _c3_merge(sequences): - """Merges MROs in *sequences* to a single MRO using the C3 algorithm. - - Adapted from http://www.python.org/download/releases/2.3/mro/. - - """ - result = [] - while True: - sequences = [s for s in sequences if s] # purge empty sequences - if not sequences: - return result - for s1 in sequences: # find merge candidates among seq heads - candidate = s1[0] - for s2 in sequences: - if candidate in s2[1:]: - candidate = None - break # reject the current head, it appears later - else: - break - if candidate is None: - raise RuntimeError("Inconsistent hierarchy") - result.append(candidate) - # remove the chosen candidate - for seq in sequences: - if seq[0] == candidate: - del seq[0] - -def _c3_mro(cls, abcs=None): - """Computes the method resolution order using extended C3 linearization. - - If no *abcs* are given, the algorithm works exactly like the built-in C3 - linearization used for method resolution. - - If given, *abcs* is a list of abstract base classes that should be inserted - into the resulting MRO. Unrelated ABCs are ignored and don't end up in the - result. The algorithm inserts ABCs where their functionality is introduced, - i.e. issubclass(cls, abc) returns True for the class itself but returns - False for all its direct base classes. Implicit ABCs for a given class - (either registered or inferred from the presence of a special method like - __len__) are inserted directly after the last ABC explicitly listed in the - MRO of said class. If two implicit ABCs end up next to each other in the - resulting MRO, their ordering depends on the order of types in *abcs*. - - """ - for i, base in enumerate(reversed(cls.__bases__)): - if hasattr(base, '__abstractmethods__'): - boundary = len(cls.__bases__) - i - break # Bases up to the last explicit ABC are considered first. - else: - boundary = 0 - abcs = list(abcs) if abcs else [] - explicit_bases = list(cls.__bases__[:boundary]) - abstract_bases = [] - other_bases = list(cls.__bases__[boundary:]) - for base in abcs: - if issubclass(cls, base) and not any( - issubclass(b, base) for b in cls.__bases__ - ): - # If *cls* is the class that introduces behaviour described by - # an ABC *base*, insert said ABC to its MRO. - abstract_bases.append(base) - for base in abstract_bases: - abcs.remove(base) - explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases] - abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases] - other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases] - return _c3_merge( - [[cls]] + - explicit_c3_mros + abstract_c3_mros + other_c3_mros + - [explicit_bases] + [abstract_bases] + [other_bases] - ) - -def _compose_mro(cls, types): - """Calculates the method resolution order for a given class *cls*. - - Includes relevant abstract base classes (with their respective bases) from - the *types* iterable. Uses a modified C3 linearization algorithm. - - """ - bases = set(cls.__mro__) - # Remove entries which are already present in the __mro__ or unrelated. - def is_related(typ): - return (typ not in bases and hasattr(typ, '__mro__') - and issubclass(cls, typ)) - types = [n for n in types if is_related(n)] - # Remove entries which are strict bases of other entries (they will end up - # in the MRO anyway. - def is_strict_base(typ): - for other in types: - if typ != other and typ in other.__mro__: - return True - return False - types = [n for n in types if not is_strict_base(n)] - # Subclasses of the ABCs in *types* which are also implemented by - # *cls* can be used to stabilize ABC ordering. - type_set = set(types) - mro = [] - for typ in types: - found = [] - for sub in typ.__subclasses__(): - if sub not in bases and issubclass(cls, sub): - found.append([s for s in sub.__mro__ if s in type_set]) - if not found: - mro.append(typ) - continue - # Favor subclasses with the biggest number of useful bases - found.sort(key=len, reverse=True) - for sub in found: - for subcls in sub: - if subcls not in mro: - mro.append(subcls) - return _c3_mro(cls, abcs=mro) - -def _find_impl(cls, registry): - """Returns the best matching implementation from *registry* for type *cls*. - - Where there is no registered implementation for a specific type, its method - resolution order is used to find a more generic implementation. - - Note: if *registry* does not contain an implementation for the base - *object* type, this function may return None. - - """ - mro = _compose_mro(cls, registry.keys()) - match = None - for t in mro: - if match is not None: - # If *match* is an implicit ABC but there is another unrelated, - # equally matching implicit ABC, refuse the temptation to guess. - if (t in registry and t not in cls.__mro__ - and match not in cls.__mro__ - and not issubclass(match, t)): - raise RuntimeError("Ambiguous dispatch: {} or {}".format( - match, t)) - break - if t in registry: - match = t - return registry.get(match) - -def singledispatch(func): - """Single-dispatch generic function decorator. - - Transforms a function into a generic function, which can have different - behaviours depending upon the type of its first argument. The decorated - function acts as the default implementation, and additional - implementations can be registered using the register() attribute of the - generic function. - """ - # There are many programs that use functools without singledispatch, so we - # trade-off making singledispatch marginally slower for the benefit of - # making start-up of such applications slightly faster. - import types, weakref - - registry = {} - dispatch_cache = weakref.WeakKeyDictionary() - cache_token = None - - def dispatch(cls): - """generic_func.dispatch(cls) -> - - Runs the dispatch algorithm to return the best available implementation - for the given *cls* registered on *generic_func*. - - """ - nonlocal cache_token - if cache_token is not None: - current_token = get_cache_token() - if cache_token != current_token: - dispatch_cache.clear() - cache_token = current_token - try: - impl = dispatch_cache[cls] - except KeyError: - try: - impl = registry[cls] - except KeyError: - impl = _find_impl(cls, registry) - dispatch_cache[cls] = impl - return impl - - def register(cls, func=None): - """generic_func.register(cls, func) -> func - - Registers a new implementation for the given *cls* on a *generic_func*. - - """ - nonlocal cache_token - if func is None: - if isinstance(cls, type): - return lambda f: register(cls, f) - ann = getattr(cls, '__annotations__', {}) - if not ann: - raise TypeError( - f"Invalid first argument to `register()`: {cls!r}. " - f"Use either `@register(some_class)` or plain `@register` " - f"on an annotated function." - ) - func = cls - - # only import typing if annotation parsing is necessary - from typing import get_type_hints - argname, cls = next(iter(get_type_hints(func).items())) - assert isinstance(cls, type), ( - f"Invalid annotation for {argname!r}. {cls!r} is not a class." - ) - registry[cls] = func - if cache_token is None and hasattr(cls, '__abstractmethods__'): - cache_token = get_cache_token() - dispatch_cache.clear() - return func - - def wrapper(*args, **kw): - if not args: - raise TypeError(f'{funcname} requires at least ' - '1 positional argument') - - return dispatch(args[0].__class__)(*args, **kw) - - funcname = getattr(func, '__name__', 'singledispatch function') - registry[object] = func - wrapper.register = register - wrapper.dispatch = dispatch - wrapper.registry = types.MappingProxyType(registry) - wrapper._clear_cache = dispatch_cache.clear - update_wrapper(wrapper, func) - return wrapper diff --git a/experiment/simulation/backend/venv/lib/python3.7/genericpath.py b/experiment/simulation/backend/venv/lib/python3.7/genericpath.py deleted file mode 100644 index 85f4a57..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/genericpath.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Path operations common to more than one OS -Do not use directly. The OS specific modules import the appropriate -functions from this module themselves. -""" -import os -import stat - -__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime', - 'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile', - 'samestat'] - - -# Does a path exist? -# This is false for dangling symbolic links on systems that support them. -def exists(path): - """Test whether a path exists. Returns False for broken symbolic links""" - try: - os.stat(path) - except OSError: - return False - return True - - -# This follows symbolic links, so both islink() and isdir() can be true -# for the same path on systems that support symlinks -def isfile(path): - """Test whether a path is a regular file""" - try: - st = os.stat(path) - except OSError: - return False - return stat.S_ISREG(st.st_mode) - - -# Is a path a directory? -# This follows symbolic links, so both islink() and isdir() -# can be true for the same path on systems that support symlinks -def isdir(s): - """Return true if the pathname refers to an existing directory.""" - try: - st = os.stat(s) - except OSError: - return False - return stat.S_ISDIR(st.st_mode) - - -def getsize(filename): - """Return the size of a file, reported by os.stat().""" - return os.stat(filename).st_size - - -def getmtime(filename): - """Return the last modification time of a file, reported by os.stat().""" - return os.stat(filename).st_mtime - - -def getatime(filename): - """Return the last access time of a file, reported by os.stat().""" - return os.stat(filename).st_atime - - -def getctime(filename): - """Return the metadata change time of a file, reported by os.stat().""" - return os.stat(filename).st_ctime - - -# Return the longest prefix of all list elements. -def commonprefix(m): - "Given a list of pathnames, returns the longest common leading component" - if not m: return '' - # Some people pass in a list of pathname parts to operate in an OS-agnostic - # fashion; don't try to translate in that case as that's an abuse of the - # API and they are already doing what they need to be OS-agnostic and so - # they most likely won't be using an os.PathLike object in the sublists. - if not isinstance(m[0], (list, tuple)): - m = tuple(map(os.fspath, m)) - s1 = min(m) - s2 = max(m) - for i, c in enumerate(s1): - if c != s2[i]: - return s1[:i] - return s1 - -# Are two stat buffers (obtained from stat, fstat or lstat) -# describing the same file? -def samestat(s1, s2): - """Test whether two stat buffers reference the same file""" - return (s1.st_ino == s2.st_ino and - s1.st_dev == s2.st_dev) - - -# Are two filenames really pointing to the same file? -def samefile(f1, f2): - """Test whether two pathnames reference the same actual file or directory - - This is determined by the device number and i-node number and - raises an exception if an os.stat() call on either pathname fails. - """ - s1 = os.stat(f1) - s2 = os.stat(f2) - return samestat(s1, s2) - - -# Are two open files really referencing the same file? -# (Not necessarily the same file descriptor!) -def sameopenfile(fp1, fp2): - """Test whether two open file objects reference the same file""" - s1 = os.fstat(fp1) - s2 = os.fstat(fp2) - return samestat(s1, s2) - - -# Split a path in root and extension. -# The extension is everything starting at the last dot in the last -# pathname component; the root is everything before that. -# It is always true that root + ext == p. - -# Generic implementation of splitext, to be parametrized with -# the separators -def _splitext(p, sep, altsep, extsep): - """Split the extension from a pathname. - - Extension is everything from the last dot to the end, ignoring - leading dots. Returns "(root, ext)"; ext may be empty.""" - # NOTE: This code must work for text and bytes strings. - - sepIndex = p.rfind(sep) - if altsep: - altsepIndex = p.rfind(altsep) - sepIndex = max(sepIndex, altsepIndex) - - dotIndex = p.rfind(extsep) - if dotIndex > sepIndex: - # skip all leading dots - filenameIndex = sepIndex + 1 - while filenameIndex < dotIndex: - if p[filenameIndex:filenameIndex+1] != extsep: - return p[:dotIndex], p[dotIndex:] - filenameIndex += 1 - - return p, p[:0] - -def _check_arg_types(funcname, *args): - hasstr = hasbytes = False - for s in args: - if isinstance(s, str): - hasstr = True - elif isinstance(s, bytes): - hasbytes = True - else: - raise TypeError('%s() argument must be str or bytes, not %r' % - (funcname, s.__class__.__name__)) from None - if hasstr and hasbytes: - raise TypeError("Can't mix strings and bytes in path components") from None diff --git a/experiment/simulation/backend/venv/lib/python3.7/hashlib.py b/experiment/simulation/backend/venv/lib/python3.7/hashlib.py deleted file mode 100644 index 4e783a8..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/hashlib.py +++ /dev/null @@ -1,252 +0,0 @@ -#. Copyright (C) 2005-2010 Gregory P. Smith (greg@krypto.org) -# Licensed to PSF under a Contributor Agreement. -# - -__doc__ = """hashlib module - A common interface to many hash functions. - -new(name, data=b'', **kwargs) - returns a new hash object implementing the - given hash function; initializing the hash - using the given binary data. - -Named constructor functions are also available, these are faster -than using new(name): - -md5(), sha1(), sha224(), sha256(), sha384(), sha512(), blake2b(), blake2s(), -sha3_224, sha3_256, sha3_384, sha3_512, shake_128, and shake_256. - -More algorithms may be available on your platform but the above are guaranteed -to exist. See the algorithms_guaranteed and algorithms_available attributes -to find out what algorithm names can be passed to new(). - -NOTE: If you want the adler32 or crc32 hash functions they are available in -the zlib module. - -Choose your hash function wisely. Some have known collision weaknesses. -sha384 and sha512 will be slow on 32 bit platforms. - -Hash objects have these methods: - - update(data): Update the hash object with the bytes in data. Repeated calls - are equivalent to a single call with the concatenation of all - the arguments. - - digest(): Return the digest of the bytes passed to the update() method - so far as a bytes object. - - hexdigest(): Like digest() except the digest is returned as a string - of double length, containing only hexadecimal digits. - - copy(): Return a copy (clone) of the hash object. This can be used to - efficiently compute the digests of datas that share a common - initial substring. - -For example, to obtain the digest of the byte string 'Nobody inspects the -spammish repetition': - - >>> import hashlib - >>> m = hashlib.md5() - >>> m.update(b"Nobody inspects") - >>> m.update(b" the spammish repetition") - >>> m.digest() - b'\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9' - -More condensed: - - >>> hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest() - 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2' - -""" - -# This tuple and __get_builtin_constructor() must be modified if a new -# always available algorithm is added. -__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', - 'blake2b', 'blake2s', - 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', - 'shake_128', 'shake_256') - - -algorithms_guaranteed = set(__always_supported) -algorithms_available = set(__always_supported) - -__all__ = __always_supported + ('new', 'algorithms_guaranteed', - 'algorithms_available', 'pbkdf2_hmac') - - -__builtin_constructor_cache = {} - -def __get_builtin_constructor(name): - cache = __builtin_constructor_cache - constructor = cache.get(name) - if constructor is not None: - return constructor - try: - if name in ('SHA1', 'sha1'): - import _sha1 - cache['SHA1'] = cache['sha1'] = _sha1.sha1 - elif name in ('MD5', 'md5'): - import _md5 - cache['MD5'] = cache['md5'] = _md5.md5 - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): - import _sha256 - cache['SHA224'] = cache['sha224'] = _sha256.sha224 - cache['SHA256'] = cache['sha256'] = _sha256.sha256 - elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): - import _sha512 - cache['SHA384'] = cache['sha384'] = _sha512.sha384 - cache['SHA512'] = cache['sha512'] = _sha512.sha512 - elif name in ('blake2b', 'blake2s'): - import _blake2 - cache['blake2b'] = _blake2.blake2b - cache['blake2s'] = _blake2.blake2s - elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', - 'shake_128', 'shake_256'}: - import _sha3 - cache['sha3_224'] = _sha3.sha3_224 - cache['sha3_256'] = _sha3.sha3_256 - cache['sha3_384'] = _sha3.sha3_384 - cache['sha3_512'] = _sha3.sha3_512 - cache['shake_128'] = _sha3.shake_128 - cache['shake_256'] = _sha3.shake_256 - except ImportError: - pass # no extension module, this hash is unsupported. - - constructor = cache.get(name) - if constructor is not None: - return constructor - - raise ValueError('unsupported hash type ' + name) - - -def __get_openssl_constructor(name): - if name in {'blake2b', 'blake2s'}: - # Prefer our blake2 implementation. - return __get_builtin_constructor(name) - try: - f = getattr(_hashlib, 'openssl_' + name) - # Allow the C module to raise ValueError. The function will be - # defined but the hash not actually available thanks to OpenSSL. - f() - # Use the C function directly (very fast) - return f - except (AttributeError, ValueError): - return __get_builtin_constructor(name) - - -def __py_new(name, data=b'', **kwargs): - """new(name, data=b'', **kwargs) - Return a new hashing object using the - named algorithm; optionally initialized with data (which must be - a bytes-like object). - """ - return __get_builtin_constructor(name)(data, **kwargs) - - -def __hash_new(name, data=b'', **kwargs): - """new(name, data=b'') - Return a new hashing object using the named algorithm; - optionally initialized with data (which must be a bytes-like object). - """ - if name in {'blake2b', 'blake2s'}: - # Prefer our blake2 implementation. - # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s. - # It does neither support keyed blake2 nor advanced features like - # salt, personal, tree hashing or SSE. - return __get_builtin_constructor(name)(data, **kwargs) - try: - return _hashlib.new(name, data) - except ValueError: - # If the _hashlib module (OpenSSL) doesn't support the named - # hash, try using our builtin implementations. - # This allows for SHA224/256 and SHA384/512 support even though - # the OpenSSL library prior to 0.9.8 doesn't provide them. - return __get_builtin_constructor(name)(data) - - -try: - import _hashlib - new = __hash_new - __get_hash = __get_openssl_constructor - algorithms_available = algorithms_available.union( - _hashlib.openssl_md_meth_names) -except ImportError: - new = __py_new - __get_hash = __get_builtin_constructor - -try: - # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA - from _hashlib import pbkdf2_hmac -except ImportError: - _trans_5C = bytes((x ^ 0x5C) for x in range(256)) - _trans_36 = bytes((x ^ 0x36) for x in range(256)) - - def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None): - """Password based key derivation function 2 (PKCS #5 v2.0) - - This Python implementations based on the hmac module about as fast - as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster - for long passwords. - """ - if not isinstance(hash_name, str): - raise TypeError(hash_name) - - if not isinstance(password, (bytes, bytearray)): - password = bytes(memoryview(password)) - if not isinstance(salt, (bytes, bytearray)): - salt = bytes(memoryview(salt)) - - # Fast inline HMAC implementation - inner = new(hash_name) - outer = new(hash_name) - blocksize = getattr(inner, 'block_size', 64) - if len(password) > blocksize: - password = new(hash_name, password).digest() - password = password + b'\x00' * (blocksize - len(password)) - inner.update(password.translate(_trans_36)) - outer.update(password.translate(_trans_5C)) - - def prf(msg, inner=inner, outer=outer): - # PBKDF2_HMAC uses the password as key. We can re-use the same - # digest objects and just update copies to skip initialization. - icpy = inner.copy() - ocpy = outer.copy() - icpy.update(msg) - ocpy.update(icpy.digest()) - return ocpy.digest() - - if iterations < 1: - raise ValueError(iterations) - if dklen is None: - dklen = outer.digest_size - if dklen < 1: - raise ValueError(dklen) - - dkey = b'' - loop = 1 - from_bytes = int.from_bytes - while len(dkey) < dklen: - prev = prf(salt + loop.to_bytes(4, 'big')) - # endianness doesn't matter here as long to / from use the same - rkey = int.from_bytes(prev, 'big') - for i in range(iterations - 1): - prev = prf(prev) - # rkey = rkey ^ prev - rkey ^= from_bytes(prev, 'big') - loop += 1 - dkey += rkey.to_bytes(inner.digest_size, 'big') - - return dkey[:dklen] - -try: - # OpenSSL's scrypt requires OpenSSL 1.1+ - from _hashlib import scrypt -except ImportError: - pass - - -for __func_name in __always_supported: - # try them all, some may not work due to the OpenSSL - # version not supporting that algorithm. - try: - globals()[__func_name] = __get_hash(__func_name) - except ValueError: - import logging - logging.exception('code for hash %s was not found.', __func_name) - - -# Cleanup locals() -del __always_supported, __func_name, __get_hash -del __py_new, __hash_new, __get_openssl_constructor diff --git a/experiment/simulation/backend/venv/lib/python3.7/heapq.py b/experiment/simulation/backend/venv/lib/python3.7/heapq.py deleted file mode 100644 index b31f418..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/heapq.py +++ /dev/null @@ -1,607 +0,0 @@ -"""Heap queue algorithm (a.k.a. priority queue). - -Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for -all k, counting elements from 0. For the sake of comparison, -non-existing elements are considered to be infinite. The interesting -property of a heap is that a[0] is always its smallest element. - -Usage: - -heap = [] # creates an empty heap -heappush(heap, item) # pushes a new item on the heap -item = heappop(heap) # pops the smallest item from the heap -item = heap[0] # smallest item on the heap without popping it -heapify(x) # transforms list into a heap, in-place, in linear time -item = heapreplace(heap, item) # pops and returns smallest item, and adds - # new item; the heap size is unchanged - -Our API differs from textbook heap algorithms as follows: - -- We use 0-based indexing. This makes the relationship between the - index for a node and the indexes for its children slightly less - obvious, but is more suitable since Python uses 0-based indexing. - -- Our heappop() method returns the smallest item, not the largest. - -These two make it possible to view the heap as a regular Python list -without surprises: heap[0] is the smallest item, and heap.sort() -maintains the heap invariant! -""" - -# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger - -__about__ = """Heap queues - -[explanation by François Pinard] - -Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for -all k, counting elements from 0. For the sake of comparison, -non-existing elements are considered to be infinite. The interesting -property of a heap is that a[0] is always its smallest element. - -The strange invariant above is meant to be an efficient memory -representation for a tournament. The numbers below are `k', not a[k]: - - 0 - - 1 2 - - 3 4 5 6 - - 7 8 9 10 11 12 13 14 - - 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 - - -In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In -a usual binary tournament we see in sports, each cell is the winner -over the two cells it tops, and we can trace the winner down the tree -to see all opponents s/he had. However, in many computer applications -of such tournaments, we do not need to trace the history of a winner. -To be more memory efficient, when a winner is promoted, we try to -replace it by something else at a lower level, and the rule becomes -that a cell and the two cells it tops contain three different items, -but the top cell "wins" over the two topped cells. - -If this heap invariant is protected at all time, index 0 is clearly -the overall winner. The simplest algorithmic way to remove it and -find the "next" winner is to move some loser (let's say cell 30 in the -diagram above) into the 0 position, and then percolate this new 0 down -the tree, exchanging values, until the invariant is re-established. -This is clearly logarithmic on the total number of items in the tree. -By iterating over all items, you get an O(n ln n) sort. - -A nice feature of this sort is that you can efficiently insert new -items while the sort is going on, provided that the inserted items are -not "better" than the last 0'th element you extracted. This is -especially useful in simulation contexts, where the tree holds all -incoming events, and the "win" condition means the smallest scheduled -time. When an event schedule other events for execution, they are -scheduled into the future, so they can easily go into the heap. So, a -heap is a good structure for implementing schedulers (this is what I -used for my MIDI sequencer :-). - -Various structures for implementing schedulers have been extensively -studied, and heaps are good for this, as they are reasonably speedy, -the speed is almost constant, and the worst case is not much different -than the average case. However, there are other representations which -are more efficient overall, yet the worst cases might be terrible. - -Heaps are also very useful in big disk sorts. You most probably all -know that a big sort implies producing "runs" (which are pre-sorted -sequences, which size is usually related to the amount of CPU memory), -followed by a merging passes for these runs, which merging is often -very cleverly organised[1]. It is very important that the initial -sort produces the longest runs possible. Tournaments are a good way -to that. If, using all the memory available to hold a tournament, you -replace and percolate items that happen to fit the current run, you'll -produce runs which are twice the size of the memory for random input, -and much better for input fuzzily ordered. - -Moreover, if you output the 0'th item on disk and get an input which -may not fit in the current tournament (because the value "wins" over -the last output value), it cannot fit in the heap, so the size of the -heap decreases. The freed memory could be cleverly reused immediately -for progressively building a second heap, which grows at exactly the -same rate the first heap is melting. When the first heap completely -vanishes, you switch heaps and start a new run. Clever and quite -effective! - -In a word, heaps are useful memory structures to know. I use them in -a few applications, and I think it is good to keep a `heap' module -around. :-) - --------------------- -[1] The disk balancing algorithms which are current, nowadays, are -more annoying than clever, and this is a consequence of the seeking -capabilities of the disks. On devices which cannot seek, like big -tape drives, the story was quite different, and one had to be very -clever to ensure (far in advance) that each tape movement will be the -most effective possible (that is, will best participate at -"progressing" the merge). Some tapes were even able to read -backwards, and this was also used to avoid the rewinding time. -Believe me, real good tape sorts were quite spectacular to watch! -From all times, sorting has always been a Great Art! :-) -""" - -__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', - 'nlargest', 'nsmallest', 'heappushpop'] - -def heappush(heap, item): - """Push item onto heap, maintaining the heap invariant.""" - heap.append(item) - _siftdown(heap, 0, len(heap)-1) - -def heappop(heap): - """Pop the smallest item off the heap, maintaining the heap invariant.""" - lastelt = heap.pop() # raises appropriate IndexError if heap is empty - if heap: - returnitem = heap[0] - heap[0] = lastelt - _siftup(heap, 0) - return returnitem - return lastelt - -def heapreplace(heap, item): - """Pop and return the current smallest value, and add the new item. - - This is more efficient than heappop() followed by heappush(), and can be - more appropriate when using a fixed-size heap. Note that the value - returned may be larger than item! That constrains reasonable uses of - this routine unless written as part of a conditional replacement: - - if item > heap[0]: - item = heapreplace(heap, item) - """ - returnitem = heap[0] # raises appropriate IndexError if heap is empty - heap[0] = item - _siftup(heap, 0) - return returnitem - -def heappushpop(heap, item): - """Fast version of a heappush followed by a heappop.""" - if heap and heap[0] < item: - item, heap[0] = heap[0], item - _siftup(heap, 0) - return item - -def heapify(x): - """Transform list into a heap, in-place, in O(len(x)) time.""" - n = len(x) - # Transform bottom-up. The largest index there's any point to looking at - # is the largest with a child index in-range, so must have 2*i + 1 < n, - # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so - # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is - # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. - for i in reversed(range(n//2)): - _siftup(x, i) - -def _heappop_max(heap): - """Maxheap version of a heappop.""" - lastelt = heap.pop() # raises appropriate IndexError if heap is empty - if heap: - returnitem = heap[0] - heap[0] = lastelt - _siftup_max(heap, 0) - return returnitem - return lastelt - -def _heapreplace_max(heap, item): - """Maxheap version of a heappop followed by a heappush.""" - returnitem = heap[0] # raises appropriate IndexError if heap is empty - heap[0] = item - _siftup_max(heap, 0) - return returnitem - -def _heapify_max(x): - """Transform list into a maxheap, in-place, in O(len(x)) time.""" - n = len(x) - for i in reversed(range(n//2)): - _siftup_max(x, i) - -# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos -# is the index of a leaf with a possibly out-of-order value. Restore the -# heap invariant. -def _siftdown(heap, startpos, pos): - newitem = heap[pos] - # Follow the path to the root, moving parents down until finding a place - # newitem fits. - while pos > startpos: - parentpos = (pos - 1) >> 1 - parent = heap[parentpos] - if newitem < parent: - heap[pos] = parent - pos = parentpos - continue - break - heap[pos] = newitem - -# The child indices of heap index pos are already heaps, and we want to make -# a heap at index pos too. We do this by bubbling the smaller child of -# pos up (and so on with that child's children, etc) until hitting a leaf, -# then using _siftdown to move the oddball originally at index pos into place. -# -# We *could* break out of the loop as soon as we find a pos where newitem <= -# both its children, but turns out that's not a good idea, and despite that -# many books write the algorithm that way. During a heap pop, the last array -# element is sifted in, and that tends to be large, so that comparing it -# against values starting from the root usually doesn't pay (= usually doesn't -# get us out of the loop early). See Knuth, Volume 3, where this is -# explained and quantified in an exercise. -# -# Cutting the # of comparisons is important, since these routines have no -# way to extract "the priority" from an array element, so that intelligence -# is likely to be hiding in custom comparison methods, or in array elements -# storing (priority, record) tuples. Comparisons are thus potentially -# expensive. -# -# On random arrays of length 1000, making this change cut the number of -# comparisons made by heapify() a little, and those made by exhaustive -# heappop() a lot, in accord with theory. Here are typical results from 3 -# runs (3 just to demonstrate how small the variance is): -# -# Compares needed by heapify Compares needed by 1000 heappops -# -------------------------- -------------------------------- -# 1837 cut to 1663 14996 cut to 8680 -# 1855 cut to 1659 14966 cut to 8678 -# 1847 cut to 1660 15024 cut to 8703 -# -# Building the heap by using heappush() 1000 times instead required -# 2198, 2148, and 2219 compares: heapify() is more efficient, when -# you can use it. -# -# The total compares needed by list.sort() on the same lists were 8627, -# 8627, and 8632 (this should be compared to the sum of heapify() and -# heappop() compares): list.sort() is (unsurprisingly!) more efficient -# for sorting. - -def _siftup(heap, pos): - endpos = len(heap) - startpos = pos - newitem = heap[pos] - # Bubble up the smaller child until hitting a leaf. - childpos = 2*pos + 1 # leftmost child position - while childpos < endpos: - # Set childpos to index of smaller child. - rightpos = childpos + 1 - if rightpos < endpos and not heap[childpos] < heap[rightpos]: - childpos = rightpos - # Move the smaller child up. - heap[pos] = heap[childpos] - pos = childpos - childpos = 2*pos + 1 - # The leaf at pos is empty now. Put newitem there, and bubble it up - # to its final resting place (by sifting its parents down). - heap[pos] = newitem - _siftdown(heap, startpos, pos) - -def _siftdown_max(heap, startpos, pos): - 'Maxheap variant of _siftdown' - newitem = heap[pos] - # Follow the path to the root, moving parents down until finding a place - # newitem fits. - while pos > startpos: - parentpos = (pos - 1) >> 1 - parent = heap[parentpos] - if parent < newitem: - heap[pos] = parent - pos = parentpos - continue - break - heap[pos] = newitem - -def _siftup_max(heap, pos): - 'Maxheap variant of _siftup' - endpos = len(heap) - startpos = pos - newitem = heap[pos] - # Bubble up the larger child until hitting a leaf. - childpos = 2*pos + 1 # leftmost child position - while childpos < endpos: - # Set childpos to index of larger child. - rightpos = childpos + 1 - if rightpos < endpos and not heap[rightpos] < heap[childpos]: - childpos = rightpos - # Move the larger child up. - heap[pos] = heap[childpos] - pos = childpos - childpos = 2*pos + 1 - # The leaf at pos is empty now. Put newitem there, and bubble it up - # to its final resting place (by sifting its parents down). - heap[pos] = newitem - _siftdown_max(heap, startpos, pos) - -def merge(*iterables, key=None, reverse=False): - '''Merge multiple sorted inputs into a single sorted output. - - Similar to sorted(itertools.chain(*iterables)) but returns a generator, - does not pull the data into memory all at once, and assumes that each of - the input streams is already sorted (smallest to largest). - - >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) - [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25] - - If *key* is not None, applies a key function to each element to determine - its sort order. - - >>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len)) - ['dog', 'cat', 'fish', 'horse', 'kangaroo'] - - ''' - - h = [] - h_append = h.append - - if reverse: - _heapify = _heapify_max - _heappop = _heappop_max - _heapreplace = _heapreplace_max - direction = -1 - else: - _heapify = heapify - _heappop = heappop - _heapreplace = heapreplace - direction = 1 - - if key is None: - for order, it in enumerate(map(iter, iterables)): - try: - next = it.__next__ - h_append([next(), order * direction, next]) - except StopIteration: - pass - _heapify(h) - while len(h) > 1: - try: - while True: - value, order, next = s = h[0] - yield value - s[0] = next() # raises StopIteration when exhausted - _heapreplace(h, s) # restore heap condition - except StopIteration: - _heappop(h) # remove empty iterator - if h: - # fast case when only a single iterator remains - value, order, next = h[0] - yield value - yield from next.__self__ - return - - for order, it in enumerate(map(iter, iterables)): - try: - next = it.__next__ - value = next() - h_append([key(value), order * direction, value, next]) - except StopIteration: - pass - _heapify(h) - while len(h) > 1: - try: - while True: - key_value, order, value, next = s = h[0] - yield value - value = next() - s[0] = key(value) - s[2] = value - _heapreplace(h, s) - except StopIteration: - _heappop(h) - if h: - key_value, order, value, next = h[0] - yield value - yield from next.__self__ - - -# Algorithm notes for nlargest() and nsmallest() -# ============================================== -# -# Make a single pass over the data while keeping the k most extreme values -# in a heap. Memory consumption is limited to keeping k values in a list. -# -# Measured performance for random inputs: -# -# number of comparisons -# n inputs k-extreme values (average of 5 trials) % more than min() -# ------------- ---------------- --------------------- ----------------- -# 1,000 100 3,317 231.7% -# 10,000 100 14,046 40.5% -# 100,000 100 105,749 5.7% -# 1,000,000 100 1,007,751 0.8% -# 10,000,000 100 10,009,401 0.1% -# -# Theoretical number of comparisons for k smallest of n random inputs: -# -# Step Comparisons Action -# ---- -------------------------- --------------------------- -# 1 1.66 * k heapify the first k-inputs -# 2 n - k compare remaining elements to top of heap -# 3 k * (1 + lg2(k)) * ln(n/k) replace the topmost value on the heap -# 4 k * lg2(k) - (k/2) final sort of the k most extreme values -# -# Combining and simplifying for a rough estimate gives: -# -# comparisons = n + k * (log(k, 2) * log(n/k) + log(k, 2) + log(n/k)) -# -# Computing the number of comparisons for step 3: -# ----------------------------------------------- -# * For the i-th new value from the iterable, the probability of being in the -# k most extreme values is k/i. For example, the probability of the 101st -# value seen being in the 100 most extreme values is 100/101. -# * If the value is a new extreme value, the cost of inserting it into the -# heap is 1 + log(k, 2). -# * The probability times the cost gives: -# (k/i) * (1 + log(k, 2)) -# * Summing across the remaining n-k elements gives: -# sum((k/i) * (1 + log(k, 2)) for i in range(k+1, n+1)) -# * This reduces to: -# (H(n) - H(k)) * k * (1 + log(k, 2)) -# * Where H(n) is the n-th harmonic number estimated by: -# gamma = 0.5772156649 -# H(n) = log(n, e) + gamma + 1 / (2 * n) -# http://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#Rate_of_divergence -# * Substituting the H(n) formula: -# comparisons = k * (1 + log(k, 2)) * (log(n/k, e) + (1/n - 1/k) / 2) -# -# Worst-case for step 3: -# ---------------------- -# In the worst case, the input data is reversed sorted so that every new element -# must be inserted in the heap: -# -# comparisons = 1.66 * k + log(k, 2) * (n - k) -# -# Alternative Algorithms -# ---------------------- -# Other algorithms were not used because they: -# 1) Took much more auxiliary memory, -# 2) Made multiple passes over the data. -# 3) Made more comparisons in common cases (small k, large n, semi-random input). -# See the more detailed comparison of approach at: -# http://code.activestate.com/recipes/577573-compare-algorithms-for-heapqsmallest - -def nsmallest(n, iterable, key=None): - """Find the n smallest elements in a dataset. - - Equivalent to: sorted(iterable, key=key)[:n] - """ - - # Short-cut for n==1 is to use min() - if n == 1: - it = iter(iterable) - sentinel = object() - if key is None: - result = min(it, default=sentinel) - else: - result = min(it, default=sentinel, key=key) - return [] if result is sentinel else [result] - - # When n>=size, it's faster to use sorted() - try: - size = len(iterable) - except (TypeError, AttributeError): - pass - else: - if n >= size: - return sorted(iterable, key=key)[:n] - - # When key is none, use simpler decoration - if key is None: - it = iter(iterable) - # put the range(n) first so that zip() doesn't - # consume one too many elements from the iterator - result = [(elem, i) for i, elem in zip(range(n), it)] - if not result: - return result - _heapify_max(result) - top = result[0][0] - order = n - _heapreplace = _heapreplace_max - for elem in it: - if elem < top: - _heapreplace(result, (elem, order)) - top, _order = result[0] - order += 1 - result.sort() - return [elem for (elem, order) in result] - - # General case, slowest method - it = iter(iterable) - result = [(key(elem), i, elem) for i, elem in zip(range(n), it)] - if not result: - return result - _heapify_max(result) - top = result[0][0] - order = n - _heapreplace = _heapreplace_max - for elem in it: - k = key(elem) - if k < top: - _heapreplace(result, (k, order, elem)) - top, _order, _elem = result[0] - order += 1 - result.sort() - return [elem for (k, order, elem) in result] - -def nlargest(n, iterable, key=None): - """Find the n largest elements in a dataset. - - Equivalent to: sorted(iterable, key=key, reverse=True)[:n] - """ - - # Short-cut for n==1 is to use max() - if n == 1: - it = iter(iterable) - sentinel = object() - if key is None: - result = max(it, default=sentinel) - else: - result = max(it, default=sentinel, key=key) - return [] if result is sentinel else [result] - - # When n>=size, it's faster to use sorted() - try: - size = len(iterable) - except (TypeError, AttributeError): - pass - else: - if n >= size: - return sorted(iterable, key=key, reverse=True)[:n] - - # When key is none, use simpler decoration - if key is None: - it = iter(iterable) - result = [(elem, i) for i, elem in zip(range(0, -n, -1), it)] - if not result: - return result - heapify(result) - top = result[0][0] - order = -n - _heapreplace = heapreplace - for elem in it: - if top < elem: - _heapreplace(result, (elem, order)) - top, _order = result[0] - order -= 1 - result.sort(reverse=True) - return [elem for (elem, order) in result] - - # General case, slowest method - it = iter(iterable) - result = [(key(elem), i, elem) for i, elem in zip(range(0, -n, -1), it)] - if not result: - return result - heapify(result) - top = result[0][0] - order = -n - _heapreplace = heapreplace - for elem in it: - k = key(elem) - if top < k: - _heapreplace(result, (k, order, elem)) - top, _order, _elem = result[0] - order -= 1 - result.sort(reverse=True) - return [elem for (k, order, elem) in result] - -# If available, use C implementation -try: - from _heapq import * -except ImportError: - pass -try: - from _heapq import _heapreplace_max -except ImportError: - pass -try: - from _heapq import _heapify_max -except ImportError: - pass -try: - from _heapq import _heappop_max -except ImportError: - pass - - -if __name__ == "__main__": - - import doctest - print(doctest.testmod()) diff --git a/experiment/simulation/backend/venv/lib/python3.7/hmac.py b/experiment/simulation/backend/venv/lib/python3.7/hmac.py deleted file mode 100644 index 43b7212..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/hmac.py +++ /dev/null @@ -1,188 +0,0 @@ -"""HMAC (Keyed-Hashing for Message Authentication) Python module. - -Implements the HMAC algorithm as described by RFC 2104. -""" - -import warnings as _warnings -from _operator import _compare_digest as compare_digest -try: - import _hashlib as _hashopenssl -except ImportError: - _hashopenssl = None - _openssl_md_meths = None -else: - _openssl_md_meths = frozenset(_hashopenssl.openssl_md_meth_names) -import hashlib as _hashlib - -trans_5C = bytes((x ^ 0x5C) for x in range(256)) -trans_36 = bytes((x ^ 0x36) for x in range(256)) - -# The size of the digests returned by HMAC depends on the underlying -# hashing module used. Use digest_size from the instance of HMAC instead. -digest_size = None - - - -class HMAC: - """RFC 2104 HMAC class. Also complies with RFC 4231. - - This supports the API for Cryptographic Hash Functions (PEP 247). - """ - blocksize = 64 # 512-bit HMAC; can be changed in subclasses. - - def __init__(self, key, msg = None, digestmod = None): - """Create a new HMAC object. - - key: key for the keyed hash object. - msg: Initial input for the hash, if provided. - digestmod: A module supporting PEP 247. *OR* - A hashlib constructor returning a new hash object. *OR* - A hash name suitable for hashlib.new(). - Defaults to hashlib.md5. - Implicit default to hashlib.md5 is deprecated since Python - 3.4 and will be removed in Python 3.8. - - Note: key and msg must be a bytes or bytearray objects. - """ - - if not isinstance(key, (bytes, bytearray)): - raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) - - if digestmod is None: - _warnings.warn("HMAC() without an explicit digestmod argument " - "is deprecated since Python 3.4, and will be removed " - "in 3.8", - DeprecationWarning, 2) - digestmod = _hashlib.md5 - - if callable(digestmod): - self.digest_cons = digestmod - elif isinstance(digestmod, str): - self.digest_cons = lambda d=b'': _hashlib.new(digestmod, d) - else: - self.digest_cons = lambda d=b'': digestmod.new(d) - - self.outer = self.digest_cons() - self.inner = self.digest_cons() - self.digest_size = self.inner.digest_size - - if hasattr(self.inner, 'block_size'): - blocksize = self.inner.block_size - if blocksize < 16: - _warnings.warn('block_size of %d seems too small; using our ' - 'default of %d.' % (blocksize, self.blocksize), - RuntimeWarning, 2) - blocksize = self.blocksize - else: - _warnings.warn('No block_size attribute on given digest object; ' - 'Assuming %d.' % (self.blocksize), - RuntimeWarning, 2) - blocksize = self.blocksize - - # self.blocksize is the default blocksize. self.block_size is - # effective block size as well as the public API attribute. - self.block_size = blocksize - - if len(key) > blocksize: - key = self.digest_cons(key).digest() - - key = key.ljust(blocksize, b'\0') - self.outer.update(key.translate(trans_5C)) - self.inner.update(key.translate(trans_36)) - if msg is not None: - self.update(msg) - - @property - def name(self): - return "hmac-" + self.inner.name - - def update(self, msg): - """Update this hashing object with the string msg. - """ - self.inner.update(msg) - - def copy(self): - """Return a separate copy of this hashing object. - - An update to this copy won't affect the original object. - """ - # Call __new__ directly to avoid the expensive __init__. - other = self.__class__.__new__(self.__class__) - other.digest_cons = self.digest_cons - other.digest_size = self.digest_size - other.inner = self.inner.copy() - other.outer = self.outer.copy() - return other - - def _current(self): - """Return a hash object for the current state. - - To be used only internally with digest() and hexdigest(). - """ - h = self.outer.copy() - h.update(self.inner.digest()) - return h - - def digest(self): - """Return the hash value of this hashing object. - - This returns a string containing 8-bit data. The object is - not altered in any way by this function; you can continue - updating the object after calling this function. - """ - h = self._current() - return h.digest() - - def hexdigest(self): - """Like digest(), but returns a string of hexadecimal digits instead. - """ - h = self._current() - return h.hexdigest() - -def new(key, msg = None, digestmod = None): - """Create a new hashing object and return it. - - key: The starting key for the hash. - msg: if available, will immediately be hashed into the object's starting - state. - - You can now feed arbitrary strings into the object using its update() - method, and can ask for the hash value at any time by calling its digest() - method. - """ - return HMAC(key, msg, digestmod) - - -def digest(key, msg, digest): - """Fast inline implementation of HMAC - - key: key for the keyed hash object. - msg: input message - digest: A hash name suitable for hashlib.new() for best performance. *OR* - A hashlib constructor returning a new hash object. *OR* - A module supporting PEP 247. - - Note: key and msg must be a bytes or bytearray objects. - """ - if (_hashopenssl is not None and - isinstance(digest, str) and digest in _openssl_md_meths): - return _hashopenssl.hmac_digest(key, msg, digest) - - if callable(digest): - digest_cons = digest - elif isinstance(digest, str): - digest_cons = lambda d=b'': _hashlib.new(digest, d) - else: - digest_cons = lambda d=b'': digest.new(d) - - inner = digest_cons() - outer = digest_cons() - blocksize = getattr(inner, 'block_size', 64) - if len(key) > blocksize: - key = digest_cons(key).digest() - key = key + b'\x00' * (blocksize - len(key)) - inner.update(key.translate(trans_36)) - outer.update(key.translate(trans_5C)) - inner.update(msg) - outer.update(inner.digest()) - return outer.digest() diff --git a/experiment/simulation/backend/venv/lib/python3.7/imp.py b/experiment/simulation/backend/venv/lib/python3.7/imp.py deleted file mode 100644 index 31f8c76..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/imp.py +++ /dev/null @@ -1,345 +0,0 @@ -"""This module provides the components needed to build your own __import__ -function. Undocumented functions are obsolete. - -In most cases it is preferred you consider using the importlib module's -functionality over this module. - -""" -# (Probably) need to stay in _imp -from _imp import (lock_held, acquire_lock, release_lock, - get_frozen_object, is_frozen_package, - init_frozen, is_builtin, is_frozen, - _fix_co_filename) -try: - from _imp import create_dynamic -except ImportError: - # Platform doesn't support dynamic loading. - create_dynamic = None - -from importlib._bootstrap import _ERR_MSG, _exec, _load, _builtin_from_name -from importlib._bootstrap_external import SourcelessFileLoader - -from importlib import machinery -from importlib import util -import importlib -import os -import sys -import tokenize -import types -import warnings - -warnings.warn("the imp module is deprecated in favour of importlib; " - "see the module's documentation for alternative uses", - DeprecationWarning, stacklevel=2) - -# DEPRECATED -SEARCH_ERROR = 0 -PY_SOURCE = 1 -PY_COMPILED = 2 -C_EXTENSION = 3 -PY_RESOURCE = 4 -PKG_DIRECTORY = 5 -C_BUILTIN = 6 -PY_FROZEN = 7 -PY_CODERESOURCE = 8 -IMP_HOOK = 9 - - -def new_module(name): - """**DEPRECATED** - - Create a new module. - - The module is not entered into sys.modules. - - """ - return types.ModuleType(name) - - -def get_magic(): - """**DEPRECATED** - - Return the magic number for .pyc files. - """ - return util.MAGIC_NUMBER - - -def get_tag(): - """Return the magic tag for .pyc files.""" - return sys.implementation.cache_tag - - -def cache_from_source(path, debug_override=None): - """**DEPRECATED** - - Given the path to a .py file, return the path to its .pyc file. - - The .py file does not need to exist; this simply returns the path to the - .pyc file calculated as if the .py file were imported. - - If debug_override is not None, then it must be a boolean and is used in - place of sys.flags.optimize. - - If sys.implementation.cache_tag is None then NotImplementedError is raised. - - """ - with warnings.catch_warnings(): - warnings.simplefilter('ignore') - return util.cache_from_source(path, debug_override) - - -def source_from_cache(path): - """**DEPRECATED** - - Given the path to a .pyc. file, return the path to its .py file. - - The .pyc file does not need to exist; this simply returns the path to - the .py file calculated to correspond to the .pyc file. If path does - not conform to PEP 3147 format, ValueError will be raised. If - sys.implementation.cache_tag is None then NotImplementedError is raised. - - """ - return util.source_from_cache(path) - - -def get_suffixes(): - """**DEPRECATED**""" - extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES] - source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES] - bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES] - - return extensions + source + bytecode - - -class NullImporter: - - """**DEPRECATED** - - Null import object. - - """ - - def __init__(self, path): - if path == '': - raise ImportError('empty pathname', path='') - elif os.path.isdir(path): - raise ImportError('existing directory', path=path) - - def find_module(self, fullname): - """Always returns None.""" - return None - - -class _HackedGetData: - - """Compatibility support for 'file' arguments of various load_*() - functions.""" - - def __init__(self, fullname, path, file=None): - super().__init__(fullname, path) - self.file = file - - def get_data(self, path): - """Gross hack to contort loader to deal w/ load_*()'s bad API.""" - if self.file and path == self.path: - # The contract of get_data() requires us to return bytes. Reopen the - # file in binary mode if needed. - if not self.file.closed: - file = self.file - if 'b' not in file.mode: - file.close() - if self.file.closed: - self.file = file = open(self.path, 'rb') - - with file: - return file.read() - else: - return super().get_data(path) - - -class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader): - - """Compatibility support for implementing load_source().""" - - -def load_source(name, pathname, file=None): - loader = _LoadSourceCompatibility(name, pathname, file) - spec = util.spec_from_file_location(name, pathname, loader=loader) - if name in sys.modules: - module = _exec(spec, sys.modules[name]) - else: - module = _load(spec) - # To allow reloading to potentially work, use a non-hacked loader which - # won't rely on a now-closed file object. - module.__loader__ = machinery.SourceFileLoader(name, pathname) - module.__spec__.loader = module.__loader__ - return module - - -class _LoadCompiledCompatibility(_HackedGetData, SourcelessFileLoader): - - """Compatibility support for implementing load_compiled().""" - - -def load_compiled(name, pathname, file=None): - """**DEPRECATED**""" - loader = _LoadCompiledCompatibility(name, pathname, file) - spec = util.spec_from_file_location(name, pathname, loader=loader) - if name in sys.modules: - module = _exec(spec, sys.modules[name]) - else: - module = _load(spec) - # To allow reloading to potentially work, use a non-hacked loader which - # won't rely on a now-closed file object. - module.__loader__ = SourcelessFileLoader(name, pathname) - module.__spec__.loader = module.__loader__ - return module - - -def load_package(name, path): - """**DEPRECATED**""" - if os.path.isdir(path): - extensions = (machinery.SOURCE_SUFFIXES[:] + - machinery.BYTECODE_SUFFIXES[:]) - for extension in extensions: - init_path = os.path.join(path, '__init__' + extension) - if os.path.exists(init_path): - path = init_path - break - else: - raise ValueError('{!r} is not a package'.format(path)) - spec = util.spec_from_file_location(name, path, - submodule_search_locations=[]) - if name in sys.modules: - return _exec(spec, sys.modules[name]) - else: - return _load(spec) - - -def load_module(name, file, filename, details): - """**DEPRECATED** - - Load a module, given information returned by find_module(). - - The module name must include the full package name, if any. - - """ - suffix, mode, type_ = details - if mode and (not mode.startswith(('r', 'U')) or '+' in mode): - raise ValueError('invalid file open mode {!r}'.format(mode)) - elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: - msg = 'file object required for import (type code {})'.format(type_) - raise ValueError(msg) - elif type_ == PY_SOURCE: - return load_source(name, filename, file) - elif type_ == PY_COMPILED: - return load_compiled(name, filename, file) - elif type_ == C_EXTENSION and load_dynamic is not None: - if file is None: - with open(filename, 'rb') as opened_file: - return load_dynamic(name, filename, opened_file) - else: - return load_dynamic(name, filename, file) - elif type_ == PKG_DIRECTORY: - return load_package(name, filename) - elif type_ == C_BUILTIN: - return init_builtin(name) - elif type_ == PY_FROZEN: - return init_frozen(name) - else: - msg = "Don't know how to import {} (type code {})".format(name, type_) - raise ImportError(msg, name=name) - - -def find_module(name, path=None): - """**DEPRECATED** - - Search for a module. - - If path is omitted or None, search for a built-in, frozen or special - module and continue search in sys.path. The module name cannot - contain '.'; to search for a submodule of a package, pass the - submodule name and the package's __path__. - - """ - if not isinstance(name, str): - raise TypeError("'name' must be a str, not {}".format(type(name))) - elif not isinstance(path, (type(None), list)): - # Backwards-compatibility - raise RuntimeError("'path' must be None or a list, " - "not {}".format(type(path))) - - if path is None: - if is_builtin(name): - return None, None, ('', '', C_BUILTIN) - elif is_frozen(name): - return None, None, ('', '', PY_FROZEN) - else: - path = sys.path - - for entry in path: - package_directory = os.path.join(entry, name) - for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]: - package_file_name = '__init__' + suffix - file_path = os.path.join(package_directory, package_file_name) - if os.path.isfile(file_path): - return None, package_directory, ('', '', PKG_DIRECTORY) - for suffix, mode, type_ in get_suffixes(): - file_name = name + suffix - file_path = os.path.join(entry, file_name) - if os.path.isfile(file_path): - break - else: - continue - break # Break out of outer loop when breaking out of inner loop. - else: - raise ImportError(_ERR_MSG.format(name), name=name) - - encoding = None - if 'b' not in mode: - with open(file_path, 'rb') as file: - encoding = tokenize.detect_encoding(file.readline)[0] - file = open(file_path, mode, encoding=encoding) - return file, file_path, (suffix, mode, type_) - - -def reload(module): - """**DEPRECATED** - - Reload the module and return it. - - The module must have been successfully imported before. - - """ - return importlib.reload(module) - - -def init_builtin(name): - """**DEPRECATED** - - Load and return a built-in module by name, or None is such module doesn't - exist - """ - try: - return _builtin_from_name(name) - except ImportError: - return None - - -if create_dynamic: - def load_dynamic(name, path, file=None): - """**DEPRECATED** - - Load an extension module. - """ - import importlib.machinery - loader = importlib.machinery.ExtensionFileLoader(name, path) - - # Issue #24748: Skip the sys.modules check in _load_module_shim; - # always load new extension - spec = importlib.machinery.ModuleSpec( - name=name, loader=loader, origin=path) - return _load(spec) - -else: - load_dynamic = None diff --git a/experiment/simulation/backend/venv/lib/python3.7/importlib b/experiment/simulation/backend/venv/lib/python3.7/importlib deleted file mode 120000 index 4c5f4ca..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/importlib +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/importlib \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/io.py b/experiment/simulation/backend/venv/lib/python3.7/io.py deleted file mode 100644 index 968ee50..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/io.py +++ /dev/null @@ -1,99 +0,0 @@ -"""The io module provides the Python interfaces to stream handling. The -builtin open function is defined in this module. - -At the top of the I/O hierarchy is the abstract base class IOBase. It -defines the basic interface to a stream. Note, however, that there is no -separation between reading and writing to streams; implementations are -allowed to raise an OSError if they do not support a given operation. - -Extending IOBase is RawIOBase which deals simply with the reading and -writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide -an interface to OS files. - -BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its -subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer -streams that are readable, writable, and both respectively. -BufferedRandom provides a buffered interface to random access -streams. BytesIO is a simple stream of in-memory bytes. - -Another IOBase subclass, TextIOBase, deals with the encoding and decoding -of streams into text. TextIOWrapper, which extends it, is a buffered text -interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO -is an in-memory stream for text. - -Argument names are not part of the specification, and only the arguments -of open() are intended to be used as keyword arguments. - -data: - -DEFAULT_BUFFER_SIZE - - An int containing the default buffer size used by the module's buffered - I/O classes. open() uses the file's blksize (as obtained by os.stat) if - possible. -""" -# New I/O library conforming to PEP 3116. - -__author__ = ("Guido van Rossum , " - "Mike Verdone , " - "Mark Russell , " - "Antoine Pitrou , " - "Amaury Forgeot d'Arc , " - "Benjamin Peterson ") - -__all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", - "BytesIO", "StringIO", "BufferedIOBase", - "BufferedReader", "BufferedWriter", "BufferedRWPair", - "BufferedRandom", "TextIOBase", "TextIOWrapper", - "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END"] - - -import _io -import abc - -from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, - open, FileIO, BytesIO, StringIO, BufferedReader, - BufferedWriter, BufferedRWPair, BufferedRandom, - IncrementalNewlineDecoder, TextIOWrapper) - -OpenWrapper = _io.open # for compatibility with _pyio - -# Pretend this exception was created here. -UnsupportedOperation.__module__ = "io" - -# for seek() -SEEK_SET = 0 -SEEK_CUR = 1 -SEEK_END = 2 - -# Declaring ABCs in C is tricky so we do it here. -# Method descriptions and default implementations are inherited from the C -# version however. -class IOBase(_io._IOBase, metaclass=abc.ABCMeta): - __doc__ = _io._IOBase.__doc__ - -class RawIOBase(_io._RawIOBase, IOBase): - __doc__ = _io._RawIOBase.__doc__ - -class BufferedIOBase(_io._BufferedIOBase, IOBase): - __doc__ = _io._BufferedIOBase.__doc__ - -class TextIOBase(_io._TextIOBase, IOBase): - __doc__ = _io._TextIOBase.__doc__ - -RawIOBase.register(FileIO) - -for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom, - BufferedRWPair): - BufferedIOBase.register(klass) - -for klass in (StringIO, TextIOWrapper): - TextIOBase.register(klass) -del klass - -try: - from _io import _WindowsConsoleIO -except ImportError: - pass -else: - RawIOBase.register(_WindowsConsoleIO) diff --git a/experiment/simulation/backend/venv/lib/python3.7/keyword.py b/experiment/simulation/backend/venv/lib/python3.7/keyword.py deleted file mode 100755 index 431991d..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/keyword.py +++ /dev/null @@ -1,96 +0,0 @@ -#! /usr/bin/env python3 - -"""Keywords (from "graminit.c") - -This file is automatically generated; please don't muck it up! - -To update the symbols in this file, 'cd' to the top directory of -the python source tree after building the interpreter and run: - - ./python Lib/keyword.py -""" - -__all__ = ["iskeyword", "kwlist"] - -kwlist = [ -#--start keywords-- - 'False', - 'None', - 'True', - 'and', - 'as', - 'assert', - 'async', - 'await', - 'break', - 'class', - 'continue', - 'def', - 'del', - 'elif', - 'else', - 'except', - 'finally', - 'for', - 'from', - 'global', - 'if', - 'import', - 'in', - 'is', - 'lambda', - 'nonlocal', - 'not', - 'or', - 'pass', - 'raise', - 'return', - 'try', - 'while', - 'with', - 'yield', -#--end keywords-- - ] - -iskeyword = frozenset(kwlist).__contains__ - -def main(): - import sys, re - - args = sys.argv[1:] - iptfile = args and args[0] or "Python/graminit.c" - if len(args) > 1: optfile = args[1] - else: optfile = "Lib/keyword.py" - - # load the output skeleton from the target, taking care to preserve its - # newline convention. - with open(optfile, newline='') as fp: - format = fp.readlines() - nl = format[0][len(format[0].strip()):] if format else '\n' - - # scan the source file for keywords - with open(iptfile) as fp: - strprog = re.compile('"([^"]+)"') - lines = [] - for line in fp: - if '{1, "' in line: - match = strprog.search(line) - if match: - lines.append(" '" + match.group(1) + "'," + nl) - lines.sort() - - # insert the lines of keywords into the skeleton - try: - start = format.index("#--start keywords--" + nl) + 1 - end = format.index("#--end keywords--" + nl) - format[start:end] = lines - except ValueError: - sys.stderr.write("target does not contain format markers\n") - sys.exit(1) - - # write the output file - with open(optfile, 'w', newline='') as fp: - fp.writelines(format) - -if __name__ == "__main__": - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/lib-dynload b/experiment/simulation/backend/venv/lib/python3.7/lib-dynload deleted file mode 120000 index 12d11db..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/lib-dynload +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python3.7/lib-dynload \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/linecache.py b/experiment/simulation/backend/venv/lib/python3.7/linecache.py deleted file mode 100644 index 3afcce1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/linecache.py +++ /dev/null @@ -1,177 +0,0 @@ -"""Cache lines from Python source files. - -This is intended to read lines from modules imported -- hence if a filename -is not found, it will look down the module search path for a file by -that name. -""" - -import functools -import sys -import os -import tokenize - -__all__ = ["getline", "clearcache", "checkcache"] - -def getline(filename, lineno, module_globals=None): - lines = getlines(filename, module_globals) - if 1 <= lineno <= len(lines): - return lines[lineno-1] - else: - return '' - - -# The cache - -# The cache. Maps filenames to either a thunk which will provide source code, -# or a tuple (size, mtime, lines, fullname) once loaded. -cache = {} - - -def clearcache(): - """Clear the cache entirely.""" - - global cache - cache = {} - - -def getlines(filename, module_globals=None): - """Get the lines for a Python source file from the cache. - Update the cache if it doesn't contain an entry for this file already.""" - - if filename in cache: - entry = cache[filename] - if len(entry) != 1: - return cache[filename][2] - - try: - return updatecache(filename, module_globals) - except MemoryError: - clearcache() - return [] - - -def checkcache(filename=None): - """Discard cache entries that are out of date. - (This is not checked upon each call!)""" - - if filename is None: - filenames = list(cache.keys()) - else: - if filename in cache: - filenames = [filename] - else: - return - - for filename in filenames: - entry = cache[filename] - if len(entry) == 1: - # lazy cache entry, leave it lazy. - continue - size, mtime, lines, fullname = entry - if mtime is None: - continue # no-op for files loaded via a __loader__ - try: - stat = os.stat(fullname) - except OSError: - del cache[filename] - continue - if size != stat.st_size or mtime != stat.st_mtime: - del cache[filename] - - -def updatecache(filename, module_globals=None): - """Update a cache entry and return its list of lines. - If something's wrong, print a message, discard the cache entry, - and return an empty list.""" - - if filename in cache: - if len(cache[filename]) != 1: - del cache[filename] - if not filename or (filename.startswith('<') and filename.endswith('>')): - return [] - - fullname = filename - try: - stat = os.stat(fullname) - except OSError: - basename = filename - - # Realise a lazy loader based lookup if there is one - # otherwise try to lookup right now. - if lazycache(filename, module_globals): - try: - data = cache[filename][0]() - except (ImportError, OSError): - pass - else: - if data is None: - # No luck, the PEP302 loader cannot find the source - # for this module. - return [] - cache[filename] = ( - len(data), None, - [line+'\n' for line in data.splitlines()], fullname - ) - return cache[filename][2] - - # Try looking through the module search path, which is only useful - # when handling a relative filename. - if os.path.isabs(filename): - return [] - - for dirname in sys.path: - try: - fullname = os.path.join(dirname, basename) - except (TypeError, AttributeError): - # Not sufficiently string-like to do anything useful with. - continue - try: - stat = os.stat(fullname) - break - except OSError: - pass - else: - return [] - try: - with tokenize.open(fullname) as fp: - lines = fp.readlines() - except OSError: - return [] - if lines and not lines[-1].endswith('\n'): - lines[-1] += '\n' - size, mtime = stat.st_size, stat.st_mtime - cache[filename] = size, mtime, lines, fullname - return lines - - -def lazycache(filename, module_globals): - """Seed the cache for filename with module_globals. - - The module loader will be asked for the source only when getlines is - called, not immediately. - - If there is an entry in the cache already, it is not altered. - - :return: True if a lazy load is registered in the cache, - otherwise False. To register such a load a module loader with a - get_source method must be found, the filename must be a cachable - filename, and the filename must not be already cached. - """ - if filename in cache: - if len(cache[filename]) == 1: - return True - else: - return False - if not filename or (filename.startswith('<') and filename.endswith('>')): - return False - # Try for a __loader__, if available - if module_globals and '__loader__' in module_globals: - name = module_globals.get('__name__') - loader = module_globals['__loader__'] - get_source = getattr(loader, 'get_source', None) - - if name and get_source: - get_lines = functools.partial(get_source, name) - cache[filename] = (get_lines,) - return True - return False diff --git a/experiment/simulation/backend/venv/lib/python3.7/locale.py b/experiment/simulation/backend/venv/lib/python3.7/locale.py deleted file mode 100644 index dd8a085..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/locale.py +++ /dev/null @@ -1,1753 +0,0 @@ -"""Locale support module. - -The module provides low-level access to the C lib's locale APIs and adds high -level number formatting APIs as well as a locale aliasing engine to complement -these. - -The aliasing engine includes support for many commonly used locale names and -maps them to values suitable for passing to the C lib's setlocale() function. It -also includes default encodings for all supported locale names. - -""" - -import sys -import encodings -import encodings.aliases -import re -import _collections_abc -from builtins import str as _builtin_str -import functools - -# Try importing the _locale module. -# -# If this fails, fall back on a basic 'C' locale emulation. - -# Yuck: LC_MESSAGES is non-standard: can't tell whether it exists before -# trying the import. So __all__ is also fiddled at the end of the file. -__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error", - "setlocale", "resetlocale", "localeconv", "strcoll", "strxfrm", - "str", "atof", "atoi", "format", "format_string", "currency", - "normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY", - "LC_NUMERIC", "LC_ALL", "CHAR_MAX"] - -def _strcoll(a,b): - """ strcoll(string,string) -> int. - Compares two strings according to the locale. - """ - return (a > b) - (a < b) - -def _strxfrm(s): - """ strxfrm(string) -> string. - Returns a string that behaves for cmp locale-aware. - """ - return s - -try: - - from _locale import * - -except ImportError: - - # Locale emulation - - CHAR_MAX = 127 - LC_ALL = 6 - LC_COLLATE = 3 - LC_CTYPE = 0 - LC_MESSAGES = 5 - LC_MONETARY = 4 - LC_NUMERIC = 1 - LC_TIME = 2 - Error = ValueError - - def localeconv(): - """ localeconv() -> dict. - Returns numeric and monetary locale-specific parameters. - """ - # 'C' locale default values - return {'grouping': [127], - 'currency_symbol': '', - 'n_sign_posn': 127, - 'p_cs_precedes': 127, - 'n_cs_precedes': 127, - 'mon_grouping': [], - 'n_sep_by_space': 127, - 'decimal_point': '.', - 'negative_sign': '', - 'positive_sign': '', - 'p_sep_by_space': 127, - 'int_curr_symbol': '', - 'p_sign_posn': 127, - 'thousands_sep': '', - 'mon_thousands_sep': '', - 'frac_digits': 127, - 'mon_decimal_point': '', - 'int_frac_digits': 127} - - def setlocale(category, value=None): - """ setlocale(integer,string=None) -> string. - Activates/queries locale processing. - """ - if value not in (None, '', 'C'): - raise Error('_locale emulation only supports "C" locale') - return 'C' - -# These may or may not exist in _locale, so be sure to set them. -if 'strxfrm' not in globals(): - strxfrm = _strxfrm -if 'strcoll' not in globals(): - strcoll = _strcoll - - -_localeconv = localeconv - -# With this dict, you can override some items of localeconv's return value. -# This is useful for testing purposes. -_override_localeconv = {} - -@functools.wraps(_localeconv) -def localeconv(): - d = _localeconv() - if _override_localeconv: - d.update(_override_localeconv) - return d - - -### Number formatting APIs - -# Author: Martin von Loewis -# improved by Georg Brandl - -# Iterate over grouping intervals -def _grouping_intervals(grouping): - last_interval = None - for interval in grouping: - # if grouping is -1, we are done - if interval == CHAR_MAX: - return - # 0: re-use last group ad infinitum - if interval == 0: - if last_interval is None: - raise ValueError("invalid grouping") - while True: - yield last_interval - yield interval - last_interval = interval - -#perform the grouping from right to left -def _group(s, monetary=False): - conv = localeconv() - thousands_sep = conv[monetary and 'mon_thousands_sep' or 'thousands_sep'] - grouping = conv[monetary and 'mon_grouping' or 'grouping'] - if not grouping: - return (s, 0) - if s[-1] == ' ': - stripped = s.rstrip() - right_spaces = s[len(stripped):] - s = stripped - else: - right_spaces = '' - left_spaces = '' - groups = [] - for interval in _grouping_intervals(grouping): - if not s or s[-1] not in "0123456789": - # only non-digit characters remain (sign, spaces) - left_spaces = s - s = '' - break - groups.append(s[-interval:]) - s = s[:-interval] - if s: - groups.append(s) - groups.reverse() - return ( - left_spaces + thousands_sep.join(groups) + right_spaces, - len(thousands_sep) * (len(groups) - 1) - ) - -# Strip a given amount of excess padding from the given string -def _strip_padding(s, amount): - lpos = 0 - while amount and s[lpos] == ' ': - lpos += 1 - amount -= 1 - rpos = len(s) - 1 - while amount and s[rpos] == ' ': - rpos -= 1 - amount -= 1 - return s[lpos:rpos+1] - -_percent_re = re.compile(r'%(?:\((?P.*?)\))?' - r'(?P[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') - -def _format(percent, value, grouping=False, monetary=False, *additional): - if additional: - formatted = percent % ((value,) + additional) - else: - formatted = percent % value - # floats and decimal ints need special action! - if percent[-1] in 'eEfFgG': - seps = 0 - parts = formatted.split('.') - if grouping: - parts[0], seps = _group(parts[0], monetary=monetary) - decimal_point = localeconv()[monetary and 'mon_decimal_point' - or 'decimal_point'] - formatted = decimal_point.join(parts) - if seps: - formatted = _strip_padding(formatted, seps) - elif percent[-1] in 'diu': - seps = 0 - if grouping: - formatted, seps = _group(formatted, monetary=monetary) - if seps: - formatted = _strip_padding(formatted, seps) - return formatted - -def format_string(f, val, grouping=False, monetary=False): - """Formats a string in the same way that the % formatting would use, - but takes the current locale into account. - - Grouping is applied if the third parameter is true. - Conversion uses monetary thousands separator and grouping strings if - forth parameter monetary is true.""" - percents = list(_percent_re.finditer(f)) - new_f = _percent_re.sub('%s', f) - - if isinstance(val, _collections_abc.Mapping): - new_val = [] - for perc in percents: - if perc.group()[-1]=='%': - new_val.append('%') - else: - new_val.append(_format(perc.group(), val, grouping, monetary)) - else: - if not isinstance(val, tuple): - val = (val,) - new_val = [] - i = 0 - for perc in percents: - if perc.group()[-1]=='%': - new_val.append('%') - else: - starcount = perc.group('modifiers').count('*') - new_val.append(_format(perc.group(), - val[i], - grouping, - monetary, - *val[i+1:i+1+starcount])) - i += (1 + starcount) - val = tuple(new_val) - - return new_f % val - -def format(percent, value, grouping=False, monetary=False, *additional): - """Deprecated, use format_string instead.""" - import warnings - warnings.warn( - "This method will be removed in a future version of Python. " - "Use 'locale.format_string()' instead.", - DeprecationWarning, stacklevel=2 - ) - - match = _percent_re.match(percent) - if not match or len(match.group())!= len(percent): - raise ValueError(("format() must be given exactly one %%char " - "format specifier, %s not valid") % repr(percent)) - return _format(percent, value, grouping, monetary, *additional) - -def currency(val, symbol=True, grouping=False, international=False): - """Formats val according to the currency settings - in the current locale.""" - conv = localeconv() - - # check for illegal values - digits = conv[international and 'int_frac_digits' or 'frac_digits'] - if digits == 127: - raise ValueError("Currency formatting is not possible using " - "the 'C' locale.") - - s = _format('%%.%if' % digits, abs(val), grouping, monetary=True) - # '<' and '>' are markers if the sign must be inserted between symbol and value - s = '<' + s + '>' - - if symbol: - smb = conv[international and 'int_curr_symbol' or 'currency_symbol'] - precedes = conv[val<0 and 'n_cs_precedes' or 'p_cs_precedes'] - separated = conv[val<0 and 'n_sep_by_space' or 'p_sep_by_space'] - - if precedes: - s = smb + (separated and ' ' or '') + s - else: - s = s + (separated and ' ' or '') + smb - - sign_pos = conv[val<0 and 'n_sign_posn' or 'p_sign_posn'] - sign = conv[val<0 and 'negative_sign' or 'positive_sign'] - - if sign_pos == 0: - s = '(' + s + ')' - elif sign_pos == 1: - s = sign + s - elif sign_pos == 2: - s = s + sign - elif sign_pos == 3: - s = s.replace('<', sign) - elif sign_pos == 4: - s = s.replace('>', sign) - else: - # the default if nothing specified; - # this should be the most fitting sign position - s = sign + s - - return s.replace('<', '').replace('>', '') - -def str(val): - """Convert float to string, taking the locale into account.""" - return _format("%.12g", val) - -def delocalize(string): - "Parses a string as a normalized number according to the locale settings." - - conv = localeconv() - - #First, get rid of the grouping - ts = conv['thousands_sep'] - if ts: - string = string.replace(ts, '') - - #next, replace the decimal point with a dot - dd = conv['decimal_point'] - if dd: - string = string.replace(dd, '.') - return string - -def atof(string, func=float): - "Parses a string as a float according to the locale settings." - return func(delocalize(string)) - -def atoi(string): - "Converts a string to an integer according to the locale settings." - return int(delocalize(string)) - -def _test(): - setlocale(LC_ALL, "") - #do grouping - s1 = format_string("%d", 123456789,1) - print(s1, "is", atoi(s1)) - #standard formatting - s1 = str(3.14) - print(s1, "is", atof(s1)) - -### Locale name aliasing engine - -# Author: Marc-Andre Lemburg, mal@lemburg.com -# Various tweaks by Fredrik Lundh - -# store away the low-level version of setlocale (it's -# overridden below) -_setlocale = setlocale - -def _replace_encoding(code, encoding): - if '.' in code: - langname = code[:code.index('.')] - else: - langname = code - # Convert the encoding to a C lib compatible encoding string - norm_encoding = encodings.normalize_encoding(encoding) - #print('norm encoding: %r' % norm_encoding) - norm_encoding = encodings.aliases.aliases.get(norm_encoding.lower(), - norm_encoding) - #print('aliased encoding: %r' % norm_encoding) - encoding = norm_encoding - norm_encoding = norm_encoding.lower() - if norm_encoding in locale_encoding_alias: - encoding = locale_encoding_alias[norm_encoding] - else: - norm_encoding = norm_encoding.replace('_', '') - norm_encoding = norm_encoding.replace('-', '') - if norm_encoding in locale_encoding_alias: - encoding = locale_encoding_alias[norm_encoding] - #print('found encoding %r' % encoding) - return langname + '.' + encoding - -def _append_modifier(code, modifier): - if modifier == 'euro': - if '.' not in code: - return code + '.ISO8859-15' - _, _, encoding = code.partition('.') - if encoding in ('ISO8859-15', 'UTF-8'): - return code - if encoding == 'ISO8859-1': - return _replace_encoding(code, 'ISO8859-15') - return code + '@' + modifier - -def normalize(localename): - - """ Returns a normalized locale code for the given locale - name. - - The returned locale code is formatted for use with - setlocale(). - - If normalization fails, the original name is returned - unchanged. - - If the given encoding is not known, the function defaults to - the default encoding for the locale code just like setlocale() - does. - - """ - # Normalize the locale name and extract the encoding and modifier - code = localename.lower() - if ':' in code: - # ':' is sometimes used as encoding delimiter. - code = code.replace(':', '.') - if '@' in code: - code, modifier = code.split('@', 1) - else: - modifier = '' - if '.' in code: - langname, encoding = code.split('.')[:2] - else: - langname = code - encoding = '' - - # First lookup: fullname (possibly with encoding and modifier) - lang_enc = langname - if encoding: - norm_encoding = encoding.replace('-', '') - norm_encoding = norm_encoding.replace('_', '') - lang_enc += '.' + norm_encoding - lookup_name = lang_enc - if modifier: - lookup_name += '@' + modifier - code = locale_alias.get(lookup_name, None) - if code is not None: - return code - #print('first lookup failed') - - if modifier: - # Second try: fullname without modifier (possibly with encoding) - code = locale_alias.get(lang_enc, None) - if code is not None: - #print('lookup without modifier succeeded') - if '@' not in code: - return _append_modifier(code, modifier) - if code.split('@', 1)[1].lower() == modifier: - return code - #print('second lookup failed') - - if encoding: - # Third try: langname (without encoding, possibly with modifier) - lookup_name = langname - if modifier: - lookup_name += '@' + modifier - code = locale_alias.get(lookup_name, None) - if code is not None: - #print('lookup without encoding succeeded') - if '@' not in code: - return _replace_encoding(code, encoding) - code, modifier = code.split('@', 1) - return _replace_encoding(code, encoding) + '@' + modifier - - if modifier: - # Fourth try: langname (without encoding and modifier) - code = locale_alias.get(langname, None) - if code is not None: - #print('lookup without modifier and encoding succeeded') - if '@' not in code: - code = _replace_encoding(code, encoding) - return _append_modifier(code, modifier) - code, defmod = code.split('@', 1) - if defmod.lower() == modifier: - return _replace_encoding(code, encoding) + '@' + defmod - - return localename - -def _parse_localename(localename): - - """ Parses the locale code for localename and returns the - result as tuple (language code, encoding). - - The localename is normalized and passed through the locale - alias engine. A ValueError is raised in case the locale name - cannot be parsed. - - The language code corresponds to RFC 1766. code and encoding - can be None in case the values cannot be determined or are - unknown to this implementation. - - """ - code = normalize(localename) - if '@' in code: - # Deal with locale modifiers - code, modifier = code.split('@', 1) - if modifier == 'euro' and '.' not in code: - # Assume Latin-9 for @euro locales. This is bogus, - # since some systems may use other encodings for these - # locales. Also, we ignore other modifiers. - return code, 'iso-8859-15' - - if '.' in code: - return tuple(code.split('.')[:2]) - elif code == 'C': - return None, None - elif code == 'UTF-8': - # On macOS "LC_CTYPE=UTF-8" is a valid locale setting - # for getting UTF-8 handling for text. - return None, 'UTF-8' - raise ValueError('unknown locale: %s' % localename) - -def _build_localename(localetuple): - - """ Builds a locale code from the given tuple (language code, - encoding). - - No aliasing or normalizing takes place. - - """ - try: - language, encoding = localetuple - - if language is None: - language = 'C' - if encoding is None: - return language - else: - return language + '.' + encoding - except (TypeError, ValueError): - raise TypeError('Locale must be None, a string, or an iterable of ' - 'two strings -- language code, encoding.') from None - -def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): - - """ Tries to determine the default locale settings and returns - them as tuple (language code, encoding). - - According to POSIX, a program which has not called - setlocale(LC_ALL, "") runs using the portable 'C' locale. - Calling setlocale(LC_ALL, "") lets it use the default locale as - defined by the LANG variable. Since we don't want to interfere - with the current locale setting we thus emulate the behavior - in the way described above. - - To maintain compatibility with other platforms, not only the - LANG variable is tested, but a list of variables given as - envvars parameter. The first found to be defined will be - used. envvars defaults to the search path used in GNU gettext; - it must always contain the variable name 'LANG'. - - Except for the code 'C', the language code corresponds to RFC - 1766. code and encoding can be None in case the values cannot - be determined. - - """ - - try: - # check if it's supported by the _locale module - import _locale - code, encoding = _locale._getdefaultlocale() - except (ImportError, AttributeError): - pass - else: - # make sure the code/encoding values are valid - if sys.platform == "win32" and code and code[:2] == "0x": - # map windows language identifier to language name - code = windows_locale.get(int(code, 0)) - # ...add other platform-specific processing here, if - # necessary... - return code, encoding - - # fall back on POSIX behaviour - import os - lookup = os.environ.get - for variable in envvars: - localename = lookup(variable,None) - if localename: - if variable == 'LANGUAGE': - localename = localename.split(':')[0] - break - else: - localename = 'C' - return _parse_localename(localename) - - -def getlocale(category=LC_CTYPE): - - """ Returns the current setting for the given locale category as - tuple (language code, encoding). - - category may be one of the LC_* value except LC_ALL. It - defaults to LC_CTYPE. - - Except for the code 'C', the language code corresponds to RFC - 1766. code and encoding can be None in case the values cannot - be determined. - - """ - localename = _setlocale(category) - if category == LC_ALL and ';' in localename: - raise TypeError('category LC_ALL is not supported') - return _parse_localename(localename) - -def setlocale(category, locale=None): - - """ Set the locale for the given category. The locale can be - a string, an iterable of two strings (language code and encoding), - or None. - - Iterables are converted to strings using the locale aliasing - engine. Locale strings are passed directly to the C lib. - - category may be given as one of the LC_* values. - - """ - if locale and not isinstance(locale, _builtin_str): - # convert to string - locale = normalize(_build_localename(locale)) - return _setlocale(category, locale) - -def resetlocale(category=LC_ALL): - - """ Sets the locale for category to the default setting. - - The default setting is determined by calling - getdefaultlocale(). category defaults to LC_ALL. - - """ - _setlocale(category, _build_localename(getdefaultlocale())) - -if sys.platform.startswith("win"): - # On Win32, this will return the ANSI code page - def getpreferredencoding(do_setlocale = True): - """Return the charset that the user is likely using.""" - if sys.flags.utf8_mode: - return 'UTF-8' - import _bootlocale - return _bootlocale.getpreferredencoding(False) -else: - # On Unix, if CODESET is available, use that. - try: - CODESET - except NameError: - if hasattr(sys, 'getandroidapilevel'): - # On Android langinfo.h and CODESET are missing, and UTF-8 is - # always used in mbstowcs() and wcstombs(). - def getpreferredencoding(do_setlocale = True): - return 'UTF-8' - else: - # Fall back to parsing environment variables :-( - def getpreferredencoding(do_setlocale = True): - """Return the charset that the user is likely using, - by looking at environment variables.""" - if sys.flags.utf8_mode: - return 'UTF-8' - res = getdefaultlocale()[1] - if res is None: - # LANG not set, default conservatively to ASCII - res = 'ascii' - return res - else: - def getpreferredencoding(do_setlocale = True): - """Return the charset that the user is likely using, - according to the system configuration.""" - if sys.flags.utf8_mode: - return 'UTF-8' - import _bootlocale - if do_setlocale: - oldloc = setlocale(LC_CTYPE) - try: - setlocale(LC_CTYPE, "") - except Error: - pass - result = _bootlocale.getpreferredencoding(False) - if do_setlocale: - setlocale(LC_CTYPE, oldloc) - return result - - -### Database -# -# The following data was extracted from the locale.alias file which -# comes with X11 and then hand edited removing the explicit encoding -# definitions and adding some more aliases. The file is usually -# available as /usr/lib/X11/locale/locale.alias. -# - -# -# The local_encoding_alias table maps lowercase encoding alias names -# to C locale encoding names (case-sensitive). Note that normalize() -# first looks up the encoding in the encodings.aliases dictionary and -# then applies this mapping to find the correct C lib name for the -# encoding. -# -locale_encoding_alias = { - - # Mappings for non-standard encoding names used in locale names - '437': 'C', - 'c': 'C', - 'en': 'ISO8859-1', - 'jis': 'JIS7', - 'jis7': 'JIS7', - 'ajec': 'eucJP', - 'koi8c': 'KOI8-C', - 'microsoftcp1251': 'CP1251', - 'microsoftcp1255': 'CP1255', - 'microsoftcp1256': 'CP1256', - '88591': 'ISO8859-1', - '88592': 'ISO8859-2', - '88595': 'ISO8859-5', - '885915': 'ISO8859-15', - - # Mappings from Python codec names to C lib encoding names - 'ascii': 'ISO8859-1', - 'latin_1': 'ISO8859-1', - 'iso8859_1': 'ISO8859-1', - 'iso8859_10': 'ISO8859-10', - 'iso8859_11': 'ISO8859-11', - 'iso8859_13': 'ISO8859-13', - 'iso8859_14': 'ISO8859-14', - 'iso8859_15': 'ISO8859-15', - 'iso8859_16': 'ISO8859-16', - 'iso8859_2': 'ISO8859-2', - 'iso8859_3': 'ISO8859-3', - 'iso8859_4': 'ISO8859-4', - 'iso8859_5': 'ISO8859-5', - 'iso8859_6': 'ISO8859-6', - 'iso8859_7': 'ISO8859-7', - 'iso8859_8': 'ISO8859-8', - 'iso8859_9': 'ISO8859-9', - 'iso2022_jp': 'JIS7', - 'shift_jis': 'SJIS', - 'tactis': 'TACTIS', - 'euc_jp': 'eucJP', - 'euc_kr': 'eucKR', - 'utf_8': 'UTF-8', - 'koi8_r': 'KOI8-R', - 'koi8_t': 'KOI8-T', - 'koi8_u': 'KOI8-U', - 'kz1048': 'RK1048', - 'cp1251': 'CP1251', - 'cp1255': 'CP1255', - 'cp1256': 'CP1256', - - # XXX This list is still incomplete. If you know more - # mappings, please file a bug report. Thanks. -} - -for k, v in sorted(locale_encoding_alias.items()): - k = k.replace('_', '') - locale_encoding_alias.setdefault(k, v) - -# -# The locale_alias table maps lowercase alias names to C locale names -# (case-sensitive). Encodings are always separated from the locale -# name using a dot ('.'); they should only be given in case the -# language name is needed to interpret the given encoding alias -# correctly (CJK codes often have this need). -# -# Note that the normalize() function which uses this tables -# removes '_' and '-' characters from the encoding part of the -# locale name before doing the lookup. This saves a lot of -# space in the table. -# -# MAL 2004-12-10: -# Updated alias mapping to most recent locale.alias file -# from X.org distribution using makelocalealias.py. -# -# These are the differences compared to the old mapping (Python 2.4 -# and older): -# -# updated 'bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' -# updated 'bg_bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' -# updated 'bulgarian' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' -# updated 'cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' -# updated 'cz_cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' -# updated 'czech' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' -# updated 'dutch' -> 'nl_BE.ISO8859-1' to 'nl_NL.ISO8859-1' -# updated 'et' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' -# updated 'et_ee' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' -# updated 'fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' -# updated 'fi_fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' -# updated 'iw' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' -# updated 'iw_il' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' -# updated 'japanese' -> 'ja_JP.SJIS' to 'ja_JP.eucJP' -# updated 'lt' -> 'lt_LT.ISO8859-4' to 'lt_LT.ISO8859-13' -# updated 'lv' -> 'lv_LV.ISO8859-4' to 'lv_LV.ISO8859-13' -# updated 'sl' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' -# updated 'slovene' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' -# updated 'th_th' -> 'th_TH.TACTIS' to 'th_TH.ISO8859-11' -# updated 'zh_cn' -> 'zh_CN.eucCN' to 'zh_CN.gb2312' -# updated 'zh_cn.big5' -> 'zh_TW.eucTW' to 'zh_TW.big5' -# updated 'zh_tw' -> 'zh_TW.eucTW' to 'zh_TW.big5' -# -# MAL 2008-05-30: -# Updated alias mapping to most recent locale.alias file -# from X.org distribution using makelocalealias.py. -# -# These are the differences compared to the old mapping (Python 2.5 -# and older): -# -# updated 'cs_cs.iso88592' -> 'cs_CZ.ISO8859-2' to 'cs_CS.ISO8859-2' -# updated 'serbocroatian' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sh' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sh_hr.iso88592' -> 'sh_HR.ISO8859-2' to 'hr_HR.ISO8859-2' -# updated 'sh_sp' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sh_yu' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sp' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sp_yu' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr_sp' -> 'sr_SP.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sr_yu' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr_yu.cp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' -# updated 'sr_yu.iso88592' -> 'sr_YU.ISO8859-2' to 'sr_CS.ISO8859-2' -# updated 'sr_yu.iso88595' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr_yu.iso88595@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# updated 'sr_yu.microsoftcp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' -# updated 'sr_yu.utf8@cyrillic' -> 'sr_YU.UTF-8' to 'sr_CS.UTF-8' -# updated 'sr_yu@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' -# -# AP 2010-04-12: -# Updated alias mapping to most recent locale.alias file -# from X.org distribution using makelocalealias.py. -# -# These are the differences compared to the old mapping (Python 2.6.5 -# and older): -# -# updated 'ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' -# updated 'ru_ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' -# updated 'serbocroatian' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' -# updated 'sh' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' -# updated 'sh_yu' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' -# updated 'sr' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' -# updated 'sr@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' -# updated 'sr@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' -# updated 'sr_cs.utf8@latn' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8@latin' -# updated 'sr_cs@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' -# updated 'sr_yu' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8@latin' -# updated 'sr_yu.utf8@cyrillic' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8' -# updated 'sr_yu@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' -# -# SS 2013-12-20: -# Updated alias mapping to most recent locale.alias file -# from X.org distribution using makelocalealias.py. -# -# These are the differences compared to the old mapping (Python 3.3.3 -# and older): -# -# updated 'a3' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' -# updated 'a3_az' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' -# updated 'a3_az.koi8c' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' -# updated 'cs_cs.iso88592' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' -# updated 'hebrew' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' -# updated 'hebrew.iso88598' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' -# updated 'sd' -> 'sd_IN@devanagari.UTF-8' to 'sd_IN.UTF-8' -# updated 'sr@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' -# updated 'sr_cs' -> 'sr_RS.UTF-8' to 'sr_CS.UTF-8' -# updated 'sr_cs.utf8@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' -# updated 'sr_cs@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' -# -# SS 2014-10-01: -# Updated alias mapping with glibc 2.19 supported locales. -# -# SS 2018-05-05: -# Updated alias mapping with glibc 2.27 supported locales. -# -# These are the differences compared to the old mapping (Python 3.6.5 -# and older): -# -# updated 'ca_es@valencia' -> 'ca_ES.ISO8859-15@valencia' to 'ca_ES.UTF-8@valencia' -# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' -# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' - -locale_alias = { - 'a3': 'az_AZ.KOI8-C', - 'a3_az': 'az_AZ.KOI8-C', - 'a3_az.koic': 'az_AZ.KOI8-C', - 'aa_dj': 'aa_DJ.ISO8859-1', - 'aa_er': 'aa_ER.UTF-8', - 'aa_et': 'aa_ET.UTF-8', - 'af': 'af_ZA.ISO8859-1', - 'af_za': 'af_ZA.ISO8859-1', - 'agr_pe': 'agr_PE.UTF-8', - 'ak_gh': 'ak_GH.UTF-8', - 'am': 'am_ET.UTF-8', - 'am_et': 'am_ET.UTF-8', - 'american': 'en_US.ISO8859-1', - 'an_es': 'an_ES.ISO8859-15', - 'anp_in': 'anp_IN.UTF-8', - 'ar': 'ar_AA.ISO8859-6', - 'ar_aa': 'ar_AA.ISO8859-6', - 'ar_ae': 'ar_AE.ISO8859-6', - 'ar_bh': 'ar_BH.ISO8859-6', - 'ar_dz': 'ar_DZ.ISO8859-6', - 'ar_eg': 'ar_EG.ISO8859-6', - 'ar_in': 'ar_IN.UTF-8', - 'ar_iq': 'ar_IQ.ISO8859-6', - 'ar_jo': 'ar_JO.ISO8859-6', - 'ar_kw': 'ar_KW.ISO8859-6', - 'ar_lb': 'ar_LB.ISO8859-6', - 'ar_ly': 'ar_LY.ISO8859-6', - 'ar_ma': 'ar_MA.ISO8859-6', - 'ar_om': 'ar_OM.ISO8859-6', - 'ar_qa': 'ar_QA.ISO8859-6', - 'ar_sa': 'ar_SA.ISO8859-6', - 'ar_sd': 'ar_SD.ISO8859-6', - 'ar_ss': 'ar_SS.UTF-8', - 'ar_sy': 'ar_SY.ISO8859-6', - 'ar_tn': 'ar_TN.ISO8859-6', - 'ar_ye': 'ar_YE.ISO8859-6', - 'arabic': 'ar_AA.ISO8859-6', - 'as': 'as_IN.UTF-8', - 'as_in': 'as_IN.UTF-8', - 'ast_es': 'ast_ES.ISO8859-15', - 'ayc_pe': 'ayc_PE.UTF-8', - 'az': 'az_AZ.ISO8859-9E', - 'az_az': 'az_AZ.ISO8859-9E', - 'az_az.iso88599e': 'az_AZ.ISO8859-9E', - 'az_ir': 'az_IR.UTF-8', - 'be': 'be_BY.CP1251', - 'be@latin': 'be_BY.UTF-8@latin', - 'be_bg.utf8': 'bg_BG.UTF-8', - 'be_by': 'be_BY.CP1251', - 'be_by@latin': 'be_BY.UTF-8@latin', - 'bem_zm': 'bem_ZM.UTF-8', - 'ber_dz': 'ber_DZ.UTF-8', - 'ber_ma': 'ber_MA.UTF-8', - 'bg': 'bg_BG.CP1251', - 'bg_bg': 'bg_BG.CP1251', - 'bhb_in.utf8': 'bhb_IN.UTF-8', - 'bho_in': 'bho_IN.UTF-8', - 'bho_np': 'bho_NP.UTF-8', - 'bi_vu': 'bi_VU.UTF-8', - 'bn_bd': 'bn_BD.UTF-8', - 'bn_in': 'bn_IN.UTF-8', - 'bo_cn': 'bo_CN.UTF-8', - 'bo_in': 'bo_IN.UTF-8', - 'bokmal': 'nb_NO.ISO8859-1', - 'bokm\xe5l': 'nb_NO.ISO8859-1', - 'br': 'br_FR.ISO8859-1', - 'br_fr': 'br_FR.ISO8859-1', - 'brx_in': 'brx_IN.UTF-8', - 'bs': 'bs_BA.ISO8859-2', - 'bs_ba': 'bs_BA.ISO8859-2', - 'bulgarian': 'bg_BG.CP1251', - 'byn_er': 'byn_ER.UTF-8', - 'c': 'C', - 'c-french': 'fr_CA.ISO8859-1', - 'c.ascii': 'C', - 'c.en': 'C', - 'c.iso88591': 'en_US.ISO8859-1', - 'c.utf8': 'en_US.UTF-8', - 'c_c': 'C', - 'c_c.c': 'C', - 'ca': 'ca_ES.ISO8859-1', - 'ca_ad': 'ca_AD.ISO8859-1', - 'ca_es': 'ca_ES.ISO8859-1', - 'ca_es@valencia': 'ca_ES.UTF-8@valencia', - 'ca_fr': 'ca_FR.ISO8859-1', - 'ca_it': 'ca_IT.ISO8859-1', - 'catalan': 'ca_ES.ISO8859-1', - 'ce_ru': 'ce_RU.UTF-8', - 'cextend': 'en_US.ISO8859-1', - 'chinese-s': 'zh_CN.eucCN', - 'chinese-t': 'zh_TW.eucTW', - 'chr_us': 'chr_US.UTF-8', - 'ckb_iq': 'ckb_IQ.UTF-8', - 'cmn_tw': 'cmn_TW.UTF-8', - 'crh_ua': 'crh_UA.UTF-8', - 'croatian': 'hr_HR.ISO8859-2', - 'cs': 'cs_CZ.ISO8859-2', - 'cs_cs': 'cs_CZ.ISO8859-2', - 'cs_cz': 'cs_CZ.ISO8859-2', - 'csb_pl': 'csb_PL.UTF-8', - 'cv_ru': 'cv_RU.UTF-8', - 'cy': 'cy_GB.ISO8859-1', - 'cy_gb': 'cy_GB.ISO8859-1', - 'cz': 'cs_CZ.ISO8859-2', - 'cz_cz': 'cs_CZ.ISO8859-2', - 'czech': 'cs_CZ.ISO8859-2', - 'da': 'da_DK.ISO8859-1', - 'da_dk': 'da_DK.ISO8859-1', - 'danish': 'da_DK.ISO8859-1', - 'dansk': 'da_DK.ISO8859-1', - 'de': 'de_DE.ISO8859-1', - 'de_at': 'de_AT.ISO8859-1', - 'de_be': 'de_BE.ISO8859-1', - 'de_ch': 'de_CH.ISO8859-1', - 'de_de': 'de_DE.ISO8859-1', - 'de_it': 'de_IT.ISO8859-1', - 'de_li.utf8': 'de_LI.UTF-8', - 'de_lu': 'de_LU.ISO8859-1', - 'deutsch': 'de_DE.ISO8859-1', - 'doi_in': 'doi_IN.UTF-8', - 'dutch': 'nl_NL.ISO8859-1', - 'dutch.iso88591': 'nl_BE.ISO8859-1', - 'dv_mv': 'dv_MV.UTF-8', - 'dz_bt': 'dz_BT.UTF-8', - 'ee': 'ee_EE.ISO8859-4', - 'ee_ee': 'ee_EE.ISO8859-4', - 'eesti': 'et_EE.ISO8859-1', - 'el': 'el_GR.ISO8859-7', - 'el_cy': 'el_CY.ISO8859-7', - 'el_gr': 'el_GR.ISO8859-7', - 'el_gr@euro': 'el_GR.ISO8859-15', - 'en': 'en_US.ISO8859-1', - 'en_ag': 'en_AG.UTF-8', - 'en_au': 'en_AU.ISO8859-1', - 'en_be': 'en_BE.ISO8859-1', - 'en_bw': 'en_BW.ISO8859-1', - 'en_ca': 'en_CA.ISO8859-1', - 'en_dk': 'en_DK.ISO8859-1', - 'en_dl.utf8': 'en_DL.UTF-8', - 'en_gb': 'en_GB.ISO8859-1', - 'en_hk': 'en_HK.ISO8859-1', - 'en_ie': 'en_IE.ISO8859-1', - 'en_il': 'en_IL.UTF-8', - 'en_in': 'en_IN.ISO8859-1', - 'en_ng': 'en_NG.UTF-8', - 'en_nz': 'en_NZ.ISO8859-1', - 'en_ph': 'en_PH.ISO8859-1', - 'en_sc.utf8': 'en_SC.UTF-8', - 'en_sg': 'en_SG.ISO8859-1', - 'en_uk': 'en_GB.ISO8859-1', - 'en_us': 'en_US.ISO8859-1', - 'en_us@euro@euro': 'en_US.ISO8859-15', - 'en_za': 'en_ZA.ISO8859-1', - 'en_zm': 'en_ZM.UTF-8', - 'en_zw': 'en_ZW.ISO8859-1', - 'en_zw.utf8': 'en_ZS.UTF-8', - 'eng_gb': 'en_GB.ISO8859-1', - 'english': 'en_EN.ISO8859-1', - 'english.iso88591': 'en_US.ISO8859-1', - 'english_uk': 'en_GB.ISO8859-1', - 'english_united-states': 'en_US.ISO8859-1', - 'english_united-states.437': 'C', - 'english_us': 'en_US.ISO8859-1', - 'eo': 'eo_XX.ISO8859-3', - 'eo.utf8': 'eo.UTF-8', - 'eo_eo': 'eo_EO.ISO8859-3', - 'eo_us.utf8': 'eo_US.UTF-8', - 'eo_xx': 'eo_XX.ISO8859-3', - 'es': 'es_ES.ISO8859-1', - 'es_ar': 'es_AR.ISO8859-1', - 'es_bo': 'es_BO.ISO8859-1', - 'es_cl': 'es_CL.ISO8859-1', - 'es_co': 'es_CO.ISO8859-1', - 'es_cr': 'es_CR.ISO8859-1', - 'es_cu': 'es_CU.UTF-8', - 'es_do': 'es_DO.ISO8859-1', - 'es_ec': 'es_EC.ISO8859-1', - 'es_es': 'es_ES.ISO8859-1', - 'es_gt': 'es_GT.ISO8859-1', - 'es_hn': 'es_HN.ISO8859-1', - 'es_mx': 'es_MX.ISO8859-1', - 'es_ni': 'es_NI.ISO8859-1', - 'es_pa': 'es_PA.ISO8859-1', - 'es_pe': 'es_PE.ISO8859-1', - 'es_pr': 'es_PR.ISO8859-1', - 'es_py': 'es_PY.ISO8859-1', - 'es_sv': 'es_SV.ISO8859-1', - 'es_us': 'es_US.ISO8859-1', - 'es_uy': 'es_UY.ISO8859-1', - 'es_ve': 'es_VE.ISO8859-1', - 'estonian': 'et_EE.ISO8859-1', - 'et': 'et_EE.ISO8859-15', - 'et_ee': 'et_EE.ISO8859-15', - 'eu': 'eu_ES.ISO8859-1', - 'eu_es': 'eu_ES.ISO8859-1', - 'eu_fr': 'eu_FR.ISO8859-1', - 'fa': 'fa_IR.UTF-8', - 'fa_ir': 'fa_IR.UTF-8', - 'fa_ir.isiri3342': 'fa_IR.ISIRI-3342', - 'ff_sn': 'ff_SN.UTF-8', - 'fi': 'fi_FI.ISO8859-15', - 'fi_fi': 'fi_FI.ISO8859-15', - 'fil_ph': 'fil_PH.UTF-8', - 'finnish': 'fi_FI.ISO8859-1', - 'fo': 'fo_FO.ISO8859-1', - 'fo_fo': 'fo_FO.ISO8859-1', - 'fr': 'fr_FR.ISO8859-1', - 'fr_be': 'fr_BE.ISO8859-1', - 'fr_ca': 'fr_CA.ISO8859-1', - 'fr_ch': 'fr_CH.ISO8859-1', - 'fr_fr': 'fr_FR.ISO8859-1', - 'fr_lu': 'fr_LU.ISO8859-1', - 'fran\xe7ais': 'fr_FR.ISO8859-1', - 'fre_fr': 'fr_FR.ISO8859-1', - 'french': 'fr_FR.ISO8859-1', - 'french.iso88591': 'fr_CH.ISO8859-1', - 'french_france': 'fr_FR.ISO8859-1', - 'fur_it': 'fur_IT.UTF-8', - 'fy_de': 'fy_DE.UTF-8', - 'fy_nl': 'fy_NL.UTF-8', - 'ga': 'ga_IE.ISO8859-1', - 'ga_ie': 'ga_IE.ISO8859-1', - 'galego': 'gl_ES.ISO8859-1', - 'galician': 'gl_ES.ISO8859-1', - 'gd': 'gd_GB.ISO8859-1', - 'gd_gb': 'gd_GB.ISO8859-1', - 'ger_de': 'de_DE.ISO8859-1', - 'german': 'de_DE.ISO8859-1', - 'german.iso88591': 'de_CH.ISO8859-1', - 'german_germany': 'de_DE.ISO8859-1', - 'gez_er': 'gez_ER.UTF-8', - 'gez_et': 'gez_ET.UTF-8', - 'gl': 'gl_ES.ISO8859-1', - 'gl_es': 'gl_ES.ISO8859-1', - 'greek': 'el_GR.ISO8859-7', - 'gu_in': 'gu_IN.UTF-8', - 'gv': 'gv_GB.ISO8859-1', - 'gv_gb': 'gv_GB.ISO8859-1', - 'ha_ng': 'ha_NG.UTF-8', - 'hak_tw': 'hak_TW.UTF-8', - 'he': 'he_IL.ISO8859-8', - 'he_il': 'he_IL.ISO8859-8', - 'hebrew': 'he_IL.ISO8859-8', - 'hi': 'hi_IN.ISCII-DEV', - 'hi_in': 'hi_IN.ISCII-DEV', - 'hi_in.isciidev': 'hi_IN.ISCII-DEV', - 'hif_fj': 'hif_FJ.UTF-8', - 'hne': 'hne_IN.UTF-8', - 'hne_in': 'hne_IN.UTF-8', - 'hr': 'hr_HR.ISO8859-2', - 'hr_hr': 'hr_HR.ISO8859-2', - 'hrvatski': 'hr_HR.ISO8859-2', - 'hsb_de': 'hsb_DE.ISO8859-2', - 'ht_ht': 'ht_HT.UTF-8', - 'hu': 'hu_HU.ISO8859-2', - 'hu_hu': 'hu_HU.ISO8859-2', - 'hungarian': 'hu_HU.ISO8859-2', - 'hy_am': 'hy_AM.UTF-8', - 'hy_am.armscii8': 'hy_AM.ARMSCII_8', - 'ia': 'ia.UTF-8', - 'ia_fr': 'ia_FR.UTF-8', - 'icelandic': 'is_IS.ISO8859-1', - 'id': 'id_ID.ISO8859-1', - 'id_id': 'id_ID.ISO8859-1', - 'ig_ng': 'ig_NG.UTF-8', - 'ik_ca': 'ik_CA.UTF-8', - 'in': 'id_ID.ISO8859-1', - 'in_id': 'id_ID.ISO8859-1', - 'is': 'is_IS.ISO8859-1', - 'is_is': 'is_IS.ISO8859-1', - 'iso-8859-1': 'en_US.ISO8859-1', - 'iso-8859-15': 'en_US.ISO8859-15', - 'iso8859-1': 'en_US.ISO8859-1', - 'iso8859-15': 'en_US.ISO8859-15', - 'iso_8859_1': 'en_US.ISO8859-1', - 'iso_8859_15': 'en_US.ISO8859-15', - 'it': 'it_IT.ISO8859-1', - 'it_ch': 'it_CH.ISO8859-1', - 'it_it': 'it_IT.ISO8859-1', - 'italian': 'it_IT.ISO8859-1', - 'iu': 'iu_CA.NUNACOM-8', - 'iu_ca': 'iu_CA.NUNACOM-8', - 'iu_ca.nunacom8': 'iu_CA.NUNACOM-8', - 'iw': 'he_IL.ISO8859-8', - 'iw_il': 'he_IL.ISO8859-8', - 'iw_il.utf8': 'iw_IL.UTF-8', - 'ja': 'ja_JP.eucJP', - 'ja_jp': 'ja_JP.eucJP', - 'ja_jp.euc': 'ja_JP.eucJP', - 'ja_jp.mscode': 'ja_JP.SJIS', - 'ja_jp.pck': 'ja_JP.SJIS', - 'japan': 'ja_JP.eucJP', - 'japanese': 'ja_JP.eucJP', - 'japanese-euc': 'ja_JP.eucJP', - 'japanese.euc': 'ja_JP.eucJP', - 'jp_jp': 'ja_JP.eucJP', - 'ka': 'ka_GE.GEORGIAN-ACADEMY', - 'ka_ge': 'ka_GE.GEORGIAN-ACADEMY', - 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', - 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', - 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', - 'kab_dz': 'kab_DZ.UTF-8', - 'kk_kz': 'kk_KZ.ptcp154', - 'kl': 'kl_GL.ISO8859-1', - 'kl_gl': 'kl_GL.ISO8859-1', - 'km_kh': 'km_KH.UTF-8', - 'kn': 'kn_IN.UTF-8', - 'kn_in': 'kn_IN.UTF-8', - 'ko': 'ko_KR.eucKR', - 'ko_kr': 'ko_KR.eucKR', - 'ko_kr.euc': 'ko_KR.eucKR', - 'kok_in': 'kok_IN.UTF-8', - 'korean': 'ko_KR.eucKR', - 'korean.euc': 'ko_KR.eucKR', - 'ks': 'ks_IN.UTF-8', - 'ks_in': 'ks_IN.UTF-8', - 'ks_in@devanagari.utf8': 'ks_IN.UTF-8@devanagari', - 'ku_tr': 'ku_TR.ISO8859-9', - 'kw': 'kw_GB.ISO8859-1', - 'kw_gb': 'kw_GB.ISO8859-1', - 'ky': 'ky_KG.UTF-8', - 'ky_kg': 'ky_KG.UTF-8', - 'lb_lu': 'lb_LU.UTF-8', - 'lg_ug': 'lg_UG.ISO8859-10', - 'li_be': 'li_BE.UTF-8', - 'li_nl': 'li_NL.UTF-8', - 'lij_it': 'lij_IT.UTF-8', - 'lithuanian': 'lt_LT.ISO8859-13', - 'ln_cd': 'ln_CD.UTF-8', - 'lo': 'lo_LA.MULELAO-1', - 'lo_la': 'lo_LA.MULELAO-1', - 'lo_la.cp1133': 'lo_LA.IBM-CP1133', - 'lo_la.ibmcp1133': 'lo_LA.IBM-CP1133', - 'lo_la.mulelao1': 'lo_LA.MULELAO-1', - 'lt': 'lt_LT.ISO8859-13', - 'lt_lt': 'lt_LT.ISO8859-13', - 'lv': 'lv_LV.ISO8859-13', - 'lv_lv': 'lv_LV.ISO8859-13', - 'lzh_tw': 'lzh_TW.UTF-8', - 'mag_in': 'mag_IN.UTF-8', - 'mai': 'mai_IN.UTF-8', - 'mai_in': 'mai_IN.UTF-8', - 'mai_np': 'mai_NP.UTF-8', - 'mfe_mu': 'mfe_MU.UTF-8', - 'mg_mg': 'mg_MG.ISO8859-15', - 'mhr_ru': 'mhr_RU.UTF-8', - 'mi': 'mi_NZ.ISO8859-1', - 'mi_nz': 'mi_NZ.ISO8859-1', - 'miq_ni': 'miq_NI.UTF-8', - 'mjw_in': 'mjw_IN.UTF-8', - 'mk': 'mk_MK.ISO8859-5', - 'mk_mk': 'mk_MK.ISO8859-5', - 'ml': 'ml_IN.UTF-8', - 'ml_in': 'ml_IN.UTF-8', - 'mn_mn': 'mn_MN.UTF-8', - 'mni_in': 'mni_IN.UTF-8', - 'mr': 'mr_IN.UTF-8', - 'mr_in': 'mr_IN.UTF-8', - 'ms': 'ms_MY.ISO8859-1', - 'ms_my': 'ms_MY.ISO8859-1', - 'mt': 'mt_MT.ISO8859-3', - 'mt_mt': 'mt_MT.ISO8859-3', - 'my_mm': 'my_MM.UTF-8', - 'nan_tw': 'nan_TW.UTF-8', - 'nb': 'nb_NO.ISO8859-1', - 'nb_no': 'nb_NO.ISO8859-1', - 'nds_de': 'nds_DE.UTF-8', - 'nds_nl': 'nds_NL.UTF-8', - 'ne_np': 'ne_NP.UTF-8', - 'nhn_mx': 'nhn_MX.UTF-8', - 'niu_nu': 'niu_NU.UTF-8', - 'niu_nz': 'niu_NZ.UTF-8', - 'nl': 'nl_NL.ISO8859-1', - 'nl_aw': 'nl_AW.UTF-8', - 'nl_be': 'nl_BE.ISO8859-1', - 'nl_nl': 'nl_NL.ISO8859-1', - 'nn': 'nn_NO.ISO8859-1', - 'nn_no': 'nn_NO.ISO8859-1', - 'no': 'no_NO.ISO8859-1', - 'no@nynorsk': 'ny_NO.ISO8859-1', - 'no_no': 'no_NO.ISO8859-1', - 'no_no.iso88591@bokmal': 'no_NO.ISO8859-1', - 'no_no.iso88591@nynorsk': 'no_NO.ISO8859-1', - 'norwegian': 'no_NO.ISO8859-1', - 'nr': 'nr_ZA.ISO8859-1', - 'nr_za': 'nr_ZA.ISO8859-1', - 'nso': 'nso_ZA.ISO8859-15', - 'nso_za': 'nso_ZA.ISO8859-15', - 'ny': 'ny_NO.ISO8859-1', - 'ny_no': 'ny_NO.ISO8859-1', - 'nynorsk': 'nn_NO.ISO8859-1', - 'oc': 'oc_FR.ISO8859-1', - 'oc_fr': 'oc_FR.ISO8859-1', - 'om_et': 'om_ET.UTF-8', - 'om_ke': 'om_KE.ISO8859-1', - 'or': 'or_IN.UTF-8', - 'or_in': 'or_IN.UTF-8', - 'os_ru': 'os_RU.UTF-8', - 'pa': 'pa_IN.UTF-8', - 'pa_in': 'pa_IN.UTF-8', - 'pa_pk': 'pa_PK.UTF-8', - 'pap_an': 'pap_AN.UTF-8', - 'pap_aw': 'pap_AW.UTF-8', - 'pap_cw': 'pap_CW.UTF-8', - 'pd': 'pd_US.ISO8859-1', - 'pd_de': 'pd_DE.ISO8859-1', - 'pd_us': 'pd_US.ISO8859-1', - 'ph': 'ph_PH.ISO8859-1', - 'ph_ph': 'ph_PH.ISO8859-1', - 'pl': 'pl_PL.ISO8859-2', - 'pl_pl': 'pl_PL.ISO8859-2', - 'polish': 'pl_PL.ISO8859-2', - 'portuguese': 'pt_PT.ISO8859-1', - 'portuguese_brazil': 'pt_BR.ISO8859-1', - 'posix': 'C', - 'posix-utf2': 'C', - 'pp': 'pp_AN.ISO8859-1', - 'pp_an': 'pp_AN.ISO8859-1', - 'ps_af': 'ps_AF.UTF-8', - 'pt': 'pt_PT.ISO8859-1', - 'pt_br': 'pt_BR.ISO8859-1', - 'pt_pt': 'pt_PT.ISO8859-1', - 'quz_pe': 'quz_PE.UTF-8', - 'raj_in': 'raj_IN.UTF-8', - 'ro': 'ro_RO.ISO8859-2', - 'ro_ro': 'ro_RO.ISO8859-2', - 'romanian': 'ro_RO.ISO8859-2', - 'ru': 'ru_RU.UTF-8', - 'ru_ru': 'ru_RU.UTF-8', - 'ru_ua': 'ru_UA.KOI8-U', - 'rumanian': 'ro_RO.ISO8859-2', - 'russian': 'ru_RU.KOI8-R', - 'rw': 'rw_RW.ISO8859-1', - 'rw_rw': 'rw_RW.ISO8859-1', - 'sa_in': 'sa_IN.UTF-8', - 'sat_in': 'sat_IN.UTF-8', - 'sc_it': 'sc_IT.UTF-8', - 'sd': 'sd_IN.UTF-8', - 'sd_in': 'sd_IN.UTF-8', - 'sd_in@devanagari.utf8': 'sd_IN.UTF-8@devanagari', - 'sd_pk': 'sd_PK.UTF-8', - 'se_no': 'se_NO.UTF-8', - 'serbocroatian': 'sr_RS.UTF-8@latin', - 'sgs_lt': 'sgs_LT.UTF-8', - 'sh': 'sr_RS.UTF-8@latin', - 'sh_ba.iso88592@bosnia': 'sr_CS.ISO8859-2', - 'sh_hr': 'sh_HR.ISO8859-2', - 'sh_hr.iso88592': 'hr_HR.ISO8859-2', - 'sh_sp': 'sr_CS.ISO8859-2', - 'sh_yu': 'sr_RS.UTF-8@latin', - 'shn_mm': 'shn_MM.UTF-8', - 'shs_ca': 'shs_CA.UTF-8', - 'si': 'si_LK.UTF-8', - 'si_lk': 'si_LK.UTF-8', - 'sid_et': 'sid_ET.UTF-8', - 'sinhala': 'si_LK.UTF-8', - 'sk': 'sk_SK.ISO8859-2', - 'sk_sk': 'sk_SK.ISO8859-2', - 'sl': 'sl_SI.ISO8859-2', - 'sl_cs': 'sl_CS.ISO8859-2', - 'sl_si': 'sl_SI.ISO8859-2', - 'slovak': 'sk_SK.ISO8859-2', - 'slovene': 'sl_SI.ISO8859-2', - 'slovenian': 'sl_SI.ISO8859-2', - 'sm_ws': 'sm_WS.UTF-8', - 'so_dj': 'so_DJ.ISO8859-1', - 'so_et': 'so_ET.UTF-8', - 'so_ke': 'so_KE.ISO8859-1', - 'so_so': 'so_SO.ISO8859-1', - 'sp': 'sr_CS.ISO8859-5', - 'sp_yu': 'sr_CS.ISO8859-5', - 'spanish': 'es_ES.ISO8859-1', - 'spanish_spain': 'es_ES.ISO8859-1', - 'sq': 'sq_AL.ISO8859-2', - 'sq_al': 'sq_AL.ISO8859-2', - 'sq_mk': 'sq_MK.UTF-8', - 'sr': 'sr_RS.UTF-8', - 'sr@cyrillic': 'sr_RS.UTF-8', - 'sr@latn': 'sr_CS.UTF-8@latin', - 'sr_cs': 'sr_CS.UTF-8', - 'sr_cs.iso88592@latn': 'sr_CS.ISO8859-2', - 'sr_cs@latn': 'sr_CS.UTF-8@latin', - 'sr_me': 'sr_ME.UTF-8', - 'sr_rs': 'sr_RS.UTF-8', - 'sr_rs@latn': 'sr_RS.UTF-8@latin', - 'sr_sp': 'sr_CS.ISO8859-2', - 'sr_yu': 'sr_RS.UTF-8@latin', - 'sr_yu.cp1251@cyrillic': 'sr_CS.CP1251', - 'sr_yu.iso88592': 'sr_CS.ISO8859-2', - 'sr_yu.iso88595': 'sr_CS.ISO8859-5', - 'sr_yu.iso88595@cyrillic': 'sr_CS.ISO8859-5', - 'sr_yu.microsoftcp1251@cyrillic': 'sr_CS.CP1251', - 'sr_yu.utf8': 'sr_RS.UTF-8', - 'sr_yu.utf8@cyrillic': 'sr_RS.UTF-8', - 'sr_yu@cyrillic': 'sr_RS.UTF-8', - 'ss': 'ss_ZA.ISO8859-1', - 'ss_za': 'ss_ZA.ISO8859-1', - 'st': 'st_ZA.ISO8859-1', - 'st_za': 'st_ZA.ISO8859-1', - 'sv': 'sv_SE.ISO8859-1', - 'sv_fi': 'sv_FI.ISO8859-1', - 'sv_se': 'sv_SE.ISO8859-1', - 'sw_ke': 'sw_KE.UTF-8', - 'sw_tz': 'sw_TZ.UTF-8', - 'swedish': 'sv_SE.ISO8859-1', - 'szl_pl': 'szl_PL.UTF-8', - 'ta': 'ta_IN.TSCII-0', - 'ta_in': 'ta_IN.TSCII-0', - 'ta_in.tscii': 'ta_IN.TSCII-0', - 'ta_in.tscii0': 'ta_IN.TSCII-0', - 'ta_lk': 'ta_LK.UTF-8', - 'tcy_in.utf8': 'tcy_IN.UTF-8', - 'te': 'te_IN.UTF-8', - 'te_in': 'te_IN.UTF-8', - 'tg': 'tg_TJ.KOI8-C', - 'tg_tj': 'tg_TJ.KOI8-C', - 'th': 'th_TH.ISO8859-11', - 'th_th': 'th_TH.ISO8859-11', - 'th_th.tactis': 'th_TH.TIS620', - 'th_th.tis620': 'th_TH.TIS620', - 'thai': 'th_TH.ISO8859-11', - 'the_np': 'the_NP.UTF-8', - 'ti_er': 'ti_ER.UTF-8', - 'ti_et': 'ti_ET.UTF-8', - 'tig_er': 'tig_ER.UTF-8', - 'tk_tm': 'tk_TM.UTF-8', - 'tl': 'tl_PH.ISO8859-1', - 'tl_ph': 'tl_PH.ISO8859-1', - 'tn': 'tn_ZA.ISO8859-15', - 'tn_za': 'tn_ZA.ISO8859-15', - 'to_to': 'to_TO.UTF-8', - 'tpi_pg': 'tpi_PG.UTF-8', - 'tr': 'tr_TR.ISO8859-9', - 'tr_cy': 'tr_CY.ISO8859-9', - 'tr_tr': 'tr_TR.ISO8859-9', - 'ts': 'ts_ZA.ISO8859-1', - 'ts_za': 'ts_ZA.ISO8859-1', - 'tt': 'tt_RU.TATAR-CYR', - 'tt_ru': 'tt_RU.TATAR-CYR', - 'tt_ru.tatarcyr': 'tt_RU.TATAR-CYR', - 'tt_ru@iqtelif': 'tt_RU.UTF-8@iqtelif', - 'turkish': 'tr_TR.ISO8859-9', - 'ug_cn': 'ug_CN.UTF-8', - 'uk': 'uk_UA.KOI8-U', - 'uk_ua': 'uk_UA.KOI8-U', - 'univ': 'en_US.utf', - 'universal': 'en_US.utf', - 'universal.utf8@ucs4': 'en_US.UTF-8', - 'unm_us': 'unm_US.UTF-8', - 'ur': 'ur_PK.CP1256', - 'ur_in': 'ur_IN.UTF-8', - 'ur_pk': 'ur_PK.CP1256', - 'uz': 'uz_UZ.UTF-8', - 'uz_uz': 'uz_UZ.UTF-8', - 'uz_uz@cyrillic': 'uz_UZ.UTF-8', - 've': 've_ZA.UTF-8', - 've_za': 've_ZA.UTF-8', - 'vi': 'vi_VN.TCVN', - 'vi_vn': 'vi_VN.TCVN', - 'vi_vn.tcvn': 'vi_VN.TCVN', - 'vi_vn.tcvn5712': 'vi_VN.TCVN', - 'vi_vn.viscii': 'vi_VN.VISCII', - 'vi_vn.viscii111': 'vi_VN.VISCII', - 'wa': 'wa_BE.ISO8859-1', - 'wa_be': 'wa_BE.ISO8859-1', - 'wae_ch': 'wae_CH.UTF-8', - 'wal_et': 'wal_ET.UTF-8', - 'wo_sn': 'wo_SN.UTF-8', - 'xh': 'xh_ZA.ISO8859-1', - 'xh_za': 'xh_ZA.ISO8859-1', - 'yi': 'yi_US.CP1255', - 'yi_us': 'yi_US.CP1255', - 'yo_ng': 'yo_NG.UTF-8', - 'yue_hk': 'yue_HK.UTF-8', - 'yuw_pg': 'yuw_PG.UTF-8', - 'zh': 'zh_CN.eucCN', - 'zh_cn': 'zh_CN.gb2312', - 'zh_cn.big5': 'zh_TW.big5', - 'zh_cn.euc': 'zh_CN.eucCN', - 'zh_hk': 'zh_HK.big5hkscs', - 'zh_hk.big5hk': 'zh_HK.big5hkscs', - 'zh_sg': 'zh_SG.GB2312', - 'zh_sg.gbk': 'zh_SG.GBK', - 'zh_tw': 'zh_TW.big5', - 'zh_tw.euc': 'zh_TW.eucTW', - 'zh_tw.euctw': 'zh_TW.eucTW', - 'zu': 'zu_ZA.ISO8859-1', - 'zu_za': 'zu_ZA.ISO8859-1', -} - -# -# This maps Windows language identifiers to locale strings. -# -# This list has been updated from -# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_238z.asp -# to include every locale up to Windows Vista. -# -# NOTE: this mapping is incomplete. If your language is missing, please -# submit a bug report to the Python bug tracker at http://bugs.python.org/ -# Make sure you include the missing language identifier and the suggested -# locale code. -# - -windows_locale = { - 0x0436: "af_ZA", # Afrikaans - 0x041c: "sq_AL", # Albanian - 0x0484: "gsw_FR",# Alsatian - France - 0x045e: "am_ET", # Amharic - Ethiopia - 0x0401: "ar_SA", # Arabic - Saudi Arabia - 0x0801: "ar_IQ", # Arabic - Iraq - 0x0c01: "ar_EG", # Arabic - Egypt - 0x1001: "ar_LY", # Arabic - Libya - 0x1401: "ar_DZ", # Arabic - Algeria - 0x1801: "ar_MA", # Arabic - Morocco - 0x1c01: "ar_TN", # Arabic - Tunisia - 0x2001: "ar_OM", # Arabic - Oman - 0x2401: "ar_YE", # Arabic - Yemen - 0x2801: "ar_SY", # Arabic - Syria - 0x2c01: "ar_JO", # Arabic - Jordan - 0x3001: "ar_LB", # Arabic - Lebanon - 0x3401: "ar_KW", # Arabic - Kuwait - 0x3801: "ar_AE", # Arabic - United Arab Emirates - 0x3c01: "ar_BH", # Arabic - Bahrain - 0x4001: "ar_QA", # Arabic - Qatar - 0x042b: "hy_AM", # Armenian - 0x044d: "as_IN", # Assamese - India - 0x042c: "az_AZ", # Azeri - Latin - 0x082c: "az_AZ", # Azeri - Cyrillic - 0x046d: "ba_RU", # Bashkir - 0x042d: "eu_ES", # Basque - Russia - 0x0423: "be_BY", # Belarusian - 0x0445: "bn_IN", # Begali - 0x201a: "bs_BA", # Bosnian - Cyrillic - 0x141a: "bs_BA", # Bosnian - Latin - 0x047e: "br_FR", # Breton - France - 0x0402: "bg_BG", # Bulgarian -# 0x0455: "my_MM", # Burmese - Not supported - 0x0403: "ca_ES", # Catalan - 0x0004: "zh_CHS",# Chinese - Simplified - 0x0404: "zh_TW", # Chinese - Taiwan - 0x0804: "zh_CN", # Chinese - PRC - 0x0c04: "zh_HK", # Chinese - Hong Kong S.A.R. - 0x1004: "zh_SG", # Chinese - Singapore - 0x1404: "zh_MO", # Chinese - Macao S.A.R. - 0x7c04: "zh_CHT",# Chinese - Traditional - 0x0483: "co_FR", # Corsican - France - 0x041a: "hr_HR", # Croatian - 0x101a: "hr_BA", # Croatian - Bosnia - 0x0405: "cs_CZ", # Czech - 0x0406: "da_DK", # Danish - 0x048c: "gbz_AF",# Dari - Afghanistan - 0x0465: "div_MV",# Divehi - Maldives - 0x0413: "nl_NL", # Dutch - The Netherlands - 0x0813: "nl_BE", # Dutch - Belgium - 0x0409: "en_US", # English - United States - 0x0809: "en_GB", # English - United Kingdom - 0x0c09: "en_AU", # English - Australia - 0x1009: "en_CA", # English - Canada - 0x1409: "en_NZ", # English - New Zealand - 0x1809: "en_IE", # English - Ireland - 0x1c09: "en_ZA", # English - South Africa - 0x2009: "en_JA", # English - Jamaica - 0x2409: "en_CB", # English - Caribbean - 0x2809: "en_BZ", # English - Belize - 0x2c09: "en_TT", # English - Trinidad - 0x3009: "en_ZW", # English - Zimbabwe - 0x3409: "en_PH", # English - Philippines - 0x4009: "en_IN", # English - India - 0x4409: "en_MY", # English - Malaysia - 0x4809: "en_IN", # English - Singapore - 0x0425: "et_EE", # Estonian - 0x0438: "fo_FO", # Faroese - 0x0464: "fil_PH",# Filipino - 0x040b: "fi_FI", # Finnish - 0x040c: "fr_FR", # French - France - 0x080c: "fr_BE", # French - Belgium - 0x0c0c: "fr_CA", # French - Canada - 0x100c: "fr_CH", # French - Switzerland - 0x140c: "fr_LU", # French - Luxembourg - 0x180c: "fr_MC", # French - Monaco - 0x0462: "fy_NL", # Frisian - Netherlands - 0x0456: "gl_ES", # Galician - 0x0437: "ka_GE", # Georgian - 0x0407: "de_DE", # German - Germany - 0x0807: "de_CH", # German - Switzerland - 0x0c07: "de_AT", # German - Austria - 0x1007: "de_LU", # German - Luxembourg - 0x1407: "de_LI", # German - Liechtenstein - 0x0408: "el_GR", # Greek - 0x046f: "kl_GL", # Greenlandic - Greenland - 0x0447: "gu_IN", # Gujarati - 0x0468: "ha_NG", # Hausa - Latin - 0x040d: "he_IL", # Hebrew - 0x0439: "hi_IN", # Hindi - 0x040e: "hu_HU", # Hungarian - 0x040f: "is_IS", # Icelandic - 0x0421: "id_ID", # Indonesian - 0x045d: "iu_CA", # Inuktitut - Syllabics - 0x085d: "iu_CA", # Inuktitut - Latin - 0x083c: "ga_IE", # Irish - Ireland - 0x0410: "it_IT", # Italian - Italy - 0x0810: "it_CH", # Italian - Switzerland - 0x0411: "ja_JP", # Japanese - 0x044b: "kn_IN", # Kannada - India - 0x043f: "kk_KZ", # Kazakh - 0x0453: "kh_KH", # Khmer - Cambodia - 0x0486: "qut_GT",# K'iche - Guatemala - 0x0487: "rw_RW", # Kinyarwanda - Rwanda - 0x0457: "kok_IN",# Konkani - 0x0412: "ko_KR", # Korean - 0x0440: "ky_KG", # Kyrgyz - 0x0454: "lo_LA", # Lao - Lao PDR - 0x0426: "lv_LV", # Latvian - 0x0427: "lt_LT", # Lithuanian - 0x082e: "dsb_DE",# Lower Sorbian - Germany - 0x046e: "lb_LU", # Luxembourgish - 0x042f: "mk_MK", # FYROM Macedonian - 0x043e: "ms_MY", # Malay - Malaysia - 0x083e: "ms_BN", # Malay - Brunei Darussalam - 0x044c: "ml_IN", # Malayalam - India - 0x043a: "mt_MT", # Maltese - 0x0481: "mi_NZ", # Maori - 0x047a: "arn_CL",# Mapudungun - 0x044e: "mr_IN", # Marathi - 0x047c: "moh_CA",# Mohawk - Canada - 0x0450: "mn_MN", # Mongolian - Cyrillic - 0x0850: "mn_CN", # Mongolian - PRC - 0x0461: "ne_NP", # Nepali - 0x0414: "nb_NO", # Norwegian - Bokmal - 0x0814: "nn_NO", # Norwegian - Nynorsk - 0x0482: "oc_FR", # Occitan - France - 0x0448: "or_IN", # Oriya - India - 0x0463: "ps_AF", # Pashto - Afghanistan - 0x0429: "fa_IR", # Persian - 0x0415: "pl_PL", # Polish - 0x0416: "pt_BR", # Portuguese - Brazil - 0x0816: "pt_PT", # Portuguese - Portugal - 0x0446: "pa_IN", # Punjabi - 0x046b: "quz_BO",# Quechua (Bolivia) - 0x086b: "quz_EC",# Quechua (Ecuador) - 0x0c6b: "quz_PE",# Quechua (Peru) - 0x0418: "ro_RO", # Romanian - Romania - 0x0417: "rm_CH", # Romansh - 0x0419: "ru_RU", # Russian - 0x243b: "smn_FI",# Sami Finland - 0x103b: "smj_NO",# Sami Norway - 0x143b: "smj_SE",# Sami Sweden - 0x043b: "se_NO", # Sami Northern Norway - 0x083b: "se_SE", # Sami Northern Sweden - 0x0c3b: "se_FI", # Sami Northern Finland - 0x203b: "sms_FI",# Sami Skolt - 0x183b: "sma_NO",# Sami Southern Norway - 0x1c3b: "sma_SE",# Sami Southern Sweden - 0x044f: "sa_IN", # Sanskrit - 0x0c1a: "sr_SP", # Serbian - Cyrillic - 0x1c1a: "sr_BA", # Serbian - Bosnia Cyrillic - 0x081a: "sr_SP", # Serbian - Latin - 0x181a: "sr_BA", # Serbian - Bosnia Latin - 0x045b: "si_LK", # Sinhala - Sri Lanka - 0x046c: "ns_ZA", # Northern Sotho - 0x0432: "tn_ZA", # Setswana - Southern Africa - 0x041b: "sk_SK", # Slovak - 0x0424: "sl_SI", # Slovenian - 0x040a: "es_ES", # Spanish - Spain - 0x080a: "es_MX", # Spanish - Mexico - 0x0c0a: "es_ES", # Spanish - Spain (Modern) - 0x100a: "es_GT", # Spanish - Guatemala - 0x140a: "es_CR", # Spanish - Costa Rica - 0x180a: "es_PA", # Spanish - Panama - 0x1c0a: "es_DO", # Spanish - Dominican Republic - 0x200a: "es_VE", # Spanish - Venezuela - 0x240a: "es_CO", # Spanish - Colombia - 0x280a: "es_PE", # Spanish - Peru - 0x2c0a: "es_AR", # Spanish - Argentina - 0x300a: "es_EC", # Spanish - Ecuador - 0x340a: "es_CL", # Spanish - Chile - 0x380a: "es_UR", # Spanish - Uruguay - 0x3c0a: "es_PY", # Spanish - Paraguay - 0x400a: "es_BO", # Spanish - Bolivia - 0x440a: "es_SV", # Spanish - El Salvador - 0x480a: "es_HN", # Spanish - Honduras - 0x4c0a: "es_NI", # Spanish - Nicaragua - 0x500a: "es_PR", # Spanish - Puerto Rico - 0x540a: "es_US", # Spanish - United States -# 0x0430: "", # Sutu - Not supported - 0x0441: "sw_KE", # Swahili - 0x041d: "sv_SE", # Swedish - Sweden - 0x081d: "sv_FI", # Swedish - Finland - 0x045a: "syr_SY",# Syriac - 0x0428: "tg_TJ", # Tajik - Cyrillic - 0x085f: "tmz_DZ",# Tamazight - Latin - 0x0449: "ta_IN", # Tamil - 0x0444: "tt_RU", # Tatar - 0x044a: "te_IN", # Telugu - 0x041e: "th_TH", # Thai - 0x0851: "bo_BT", # Tibetan - Bhutan - 0x0451: "bo_CN", # Tibetan - PRC - 0x041f: "tr_TR", # Turkish - 0x0442: "tk_TM", # Turkmen - Cyrillic - 0x0480: "ug_CN", # Uighur - Arabic - 0x0422: "uk_UA", # Ukrainian - 0x042e: "wen_DE",# Upper Sorbian - Germany - 0x0420: "ur_PK", # Urdu - 0x0820: "ur_IN", # Urdu - India - 0x0443: "uz_UZ", # Uzbek - Latin - 0x0843: "uz_UZ", # Uzbek - Cyrillic - 0x042a: "vi_VN", # Vietnamese - 0x0452: "cy_GB", # Welsh - 0x0488: "wo_SN", # Wolof - Senegal - 0x0434: "xh_ZA", # Xhosa - South Africa - 0x0485: "sah_RU",# Yakut - Cyrillic - 0x0478: "ii_CN", # Yi - PRC - 0x046a: "yo_NG", # Yoruba - Nigeria - 0x0435: "zu_ZA", # Zulu -} - -def _print_locale(): - - """ Test function. - """ - categories = {} - def _init_categories(categories=categories): - for k,v in globals().items(): - if k[:3] == 'LC_': - categories[k] = v - _init_categories() - del categories['LC_ALL'] - - print('Locale defaults as determined by getdefaultlocale():') - print('-'*72) - lang, enc = getdefaultlocale() - print('Language: ', lang or '(undefined)') - print('Encoding: ', enc or '(undefined)') - print() - - print('Locale settings on startup:') - print('-'*72) - for name,category in categories.items(): - print(name, '...') - lang, enc = getlocale(category) - print(' Language: ', lang or '(undefined)') - print(' Encoding: ', enc or '(undefined)') - print() - - print() - print('Locale settings after calling resetlocale():') - print('-'*72) - resetlocale() - for name,category in categories.items(): - print(name, '...') - lang, enc = getlocale(category) - print(' Language: ', lang or '(undefined)') - print(' Encoding: ', enc or '(undefined)') - print() - - try: - setlocale(LC_ALL, "") - except: - print('NOTE:') - print('setlocale(LC_ALL, "") does not support the default locale') - print('given in the OS environment variables.') - else: - print() - print('Locale settings after calling setlocale(LC_ALL, ""):') - print('-'*72) - for name,category in categories.items(): - print(name, '...') - lang, enc = getlocale(category) - print(' Language: ', lang or '(undefined)') - print(' Encoding: ', enc or '(undefined)') - print() - -### - -try: - LC_MESSAGES -except NameError: - pass -else: - __all__.append("LC_MESSAGES") - -if __name__=='__main__': - print('Locale aliasing:') - print() - _print_locale() - print() - print('Number formatting:') - print() - _test() diff --git a/experiment/simulation/backend/venv/lib/python3.7/no-global-site-packages.txt b/experiment/simulation/backend/venv/lib/python3.7/no-global-site-packages.txt deleted file mode 100644 index e69de29..0000000 diff --git a/experiment/simulation/backend/venv/lib/python3.7/ntpath.py b/experiment/simulation/backend/venv/lib/python3.7/ntpath.py deleted file mode 100644 index 3c820b5..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/ntpath.py +++ /dev/null @@ -1,669 +0,0 @@ -# Module 'ntpath' -- common operations on WinNT/Win95 pathnames -"""Common pathname manipulations, WindowsNT/95 version. - -Instead of importing this module directly, import os and refer to this -module as os.path. -""" - -# strings representing various path-related bits and pieces -# These are primarily for export; internally, they are hardcoded. -# Should be set before imports for resolving cyclic dependency. -curdir = '.' -pardir = '..' -extsep = '.' -sep = '\\' -pathsep = ';' -altsep = '/' -defpath = '.;C:\\bin' -devnull = 'nul' - -import os -import sys -import stat -import genericpath -from genericpath import * - -__all__ = ["normcase","isabs","join","splitdrive","split","splitext", - "basename","dirname","commonprefix","getsize","getmtime", - "getatime","getctime", "islink","exists","lexists","isdir","isfile", - "ismount", "expanduser","expandvars","normpath","abspath", - "curdir","pardir","sep","pathsep","defpath","altsep", - "extsep","devnull","realpath","supports_unicode_filenames","relpath", - "samefile", "sameopenfile", "samestat", "commonpath"] - -def _get_bothseps(path): - if isinstance(path, bytes): - return b'\\/' - else: - return '\\/' - -# Normalize the case of a pathname and map slashes to backslashes. -# Other normalizations (such as optimizing '../' away) are not done -# (this is done by normpath). - -def normcase(s): - """Normalize case of pathname. - - Makes all characters lowercase and all slashes into backslashes.""" - s = os.fspath(s) - try: - if isinstance(s, bytes): - return s.replace(b'/', b'\\').lower() - else: - return s.replace('/', '\\').lower() - except (TypeError, AttributeError): - if not isinstance(s, (bytes, str)): - raise TypeError("normcase() argument must be str or bytes, " - "not %r" % s.__class__.__name__) from None - raise - - -# Return whether a path is absolute. -# Trivial in Posix, harder on Windows. -# For Windows it is absolute if it starts with a slash or backslash (current -# volume), or if a pathname after the volume-letter-and-colon or UNC-resource -# starts with a slash or backslash. - -def isabs(s): - """Test whether a path is absolute""" - s = os.fspath(s) - s = splitdrive(s)[1] - return len(s) > 0 and s[0] in _get_bothseps(s) - - -# Join two (or more) paths. -def join(path, *paths): - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'\\' - seps = b'\\/' - colon = b':' - else: - sep = '\\' - seps = '\\/' - colon = ':' - try: - if not paths: - path[:0] + sep #23780: Ensure compatible data type even if p is null. - result_drive, result_path = splitdrive(path) - for p in map(os.fspath, paths): - p_drive, p_path = splitdrive(p) - if p_path and p_path[0] in seps: - # Second path is absolute - if p_drive or not result_drive: - result_drive = p_drive - result_path = p_path - continue - elif p_drive and p_drive != result_drive: - if p_drive.lower() != result_drive.lower(): - # Different drives => ignore the first path entirely - result_drive = p_drive - result_path = p_path - continue - # Same drive in different case - result_drive = p_drive - # Second path is relative to the first - if result_path and result_path[-1] not in seps: - result_path = result_path + sep - result_path = result_path + p_path - ## add separator between UNC and non-absolute path - if (result_path and result_path[0] not in seps and - result_drive and result_drive[-1:] != colon): - return result_drive + sep + result_path - return result_drive + result_path - except (TypeError, AttributeError, BytesWarning): - genericpath._check_arg_types('join', path, *paths) - raise - - -# Split a path in a drive specification (a drive letter followed by a -# colon) and the path specification. -# It is always true that drivespec + pathspec == p -def splitdrive(p): - """Split a pathname into drive/UNC sharepoint and relative path specifiers. - Returns a 2-tuple (drive_or_unc, path); either part may be empty. - - If you assign - result = splitdrive(p) - It is always true that: - result[0] + result[1] == p - - If the path contained a drive letter, drive_or_unc will contain everything - up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir") - - If the path contained a UNC path, the drive_or_unc will contain the host name - and share up to but not including the fourth directory separator character. - e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir") - - Paths cannot contain both a drive letter and a UNC path. - - """ - p = os.fspath(p) - if len(p) >= 2: - if isinstance(p, bytes): - sep = b'\\' - altsep = b'/' - colon = b':' - else: - sep = '\\' - altsep = '/' - colon = ':' - normp = p.replace(altsep, sep) - if (normp[0:2] == sep*2) and (normp[2:3] != sep): - # is a UNC path: - # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path - # \\machine\mountpoint\directory\etc\... - # directory ^^^^^^^^^^^^^^^ - index = normp.find(sep, 2) - if index == -1: - return p[:0], p - index2 = normp.find(sep, index + 1) - # a UNC path can't have two slashes in a row - # (after the initial two) - if index2 == index + 1: - return p[:0], p - if index2 == -1: - index2 = len(p) - return p[:index2], p[index2:] - if normp[1:2] == colon: - return p[:2], p[2:] - return p[:0], p - - -# Split a path in head (everything up to the last '/') and tail (the -# rest). After the trailing '/' is stripped, the invariant -# join(head, tail) == p holds. -# The resulting head won't end in '/' unless it is the root. - -def split(p): - """Split a pathname. - - Return tuple (head, tail) where tail is everything after the final slash. - Either part may be empty.""" - p = os.fspath(p) - seps = _get_bothseps(p) - d, p = splitdrive(p) - # set i to index beyond p's last slash - i = len(p) - while i and p[i-1] not in seps: - i -= 1 - head, tail = p[:i], p[i:] # now tail has no slashes - # remove trailing slashes from head, unless it's all slashes - head = head.rstrip(seps) or head - return d + head, tail - - -# Split a path in root and extension. -# The extension is everything starting at the last dot in the last -# pathname component; the root is everything before that. -# It is always true that root + ext == p. - -def splitext(p): - p = os.fspath(p) - if isinstance(p, bytes): - return genericpath._splitext(p, b'\\', b'/', b'.') - else: - return genericpath._splitext(p, '\\', '/', '.') -splitext.__doc__ = genericpath._splitext.__doc__ - - -# Return the tail (basename) part of a path. - -def basename(p): - """Returns the final component of a pathname""" - return split(p)[1] - - -# Return the head (dirname) part of a path. - -def dirname(p): - """Returns the directory component of a pathname""" - return split(p)[0] - -# Is a path a symbolic link? -# This will always return false on systems where os.lstat doesn't exist. - -def islink(path): - """Test whether a path is a symbolic link. - This will always return false for Windows prior to 6.0. - """ - try: - st = os.lstat(path) - except (OSError, AttributeError): - return False - return stat.S_ISLNK(st.st_mode) - -# Being true for dangling symbolic links is also useful. - -def lexists(path): - """Test whether a path exists. Returns True for broken symbolic links""" - try: - st = os.lstat(path) - except OSError: - return False - return True - -# Is a path a mount point? -# Any drive letter root (eg c:\) -# Any share UNC (eg \\server\share) -# Any volume mounted on a filesystem folder -# -# No one method detects all three situations. Historically we've lexically -# detected drive letter roots and share UNCs. The canonical approach to -# detecting mounted volumes (querying the reparse tag) fails for the most -# common case: drive letter roots. The alternative which uses GetVolumePathName -# fails if the drive letter is the result of a SUBST. -try: - from nt import _getvolumepathname -except ImportError: - _getvolumepathname = None -def ismount(path): - """Test whether a path is a mount point (a drive root, the root of a - share, or a mounted volume)""" - path = os.fspath(path) - seps = _get_bothseps(path) - path = abspath(path) - root, rest = splitdrive(path) - if root and root[0] in seps: - return (not rest) or (rest in seps) - if rest in seps: - return True - - if _getvolumepathname: - return path.rstrip(seps) == _getvolumepathname(path).rstrip(seps) - else: - return False - - -# Expand paths beginning with '~' or '~user'. -# '~' means $HOME; '~user' means that user's home directory. -# If the path doesn't begin with '~', or if the user or $HOME is unknown, -# the path is returned unchanged (leaving error reporting to whatever -# function is called with the expanded path as argument). -# See also module 'glob' for expansion of *, ? and [...] in pathnames. -# (A function should also be defined to do full *sh-style environment -# variable expansion.) - -def expanduser(path): - """Expand ~ and ~user constructs. - - If user or $HOME is unknown, do nothing.""" - path = os.fspath(path) - if isinstance(path, bytes): - tilde = b'~' - else: - tilde = '~' - if not path.startswith(tilde): - return path - i, n = 1, len(path) - while i < n and path[i] not in _get_bothseps(path): - i += 1 - - if 'HOME' in os.environ: - userhome = os.environ['HOME'] - elif 'USERPROFILE' in os.environ: - userhome = os.environ['USERPROFILE'] - elif not 'HOMEPATH' in os.environ: - return path - else: - try: - drive = os.environ['HOMEDRIVE'] - except KeyError: - drive = '' - userhome = join(drive, os.environ['HOMEPATH']) - - if isinstance(path, bytes): - userhome = os.fsencode(userhome) - - if i != 1: #~user - userhome = join(dirname(userhome), path[1:i]) - - return userhome + path[i:] - - -# Expand paths containing shell variable substitutions. -# The following rules apply: -# - no expansion within single quotes -# - '$$' is translated into '$' -# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2% -# - ${varname} is accepted. -# - $varname is accepted. -# - %varname% is accepted. -# - varnames can be made out of letters, digits and the characters '_-' -# (though is not verified in the ${varname} and %varname% cases) -# XXX With COMMAND.COM you can use any characters in a variable name, -# XXX except '^|<>='. - -def expandvars(path): - """Expand shell variables of the forms $var, ${var} and %var%. - - Unknown variables are left unchanged.""" - path = os.fspath(path) - if isinstance(path, bytes): - if b'$' not in path and b'%' not in path: - return path - import string - varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii') - quote = b'\'' - percent = b'%' - brace = b'{' - rbrace = b'}' - dollar = b'$' - environ = getattr(os, 'environb', None) - else: - if '$' not in path and '%' not in path: - return path - import string - varchars = string.ascii_letters + string.digits + '_-' - quote = '\'' - percent = '%' - brace = '{' - rbrace = '}' - dollar = '$' - environ = os.environ - res = path[:0] - index = 0 - pathlen = len(path) - while index < pathlen: - c = path[index:index+1] - if c == quote: # no expansion within single quotes - path = path[index + 1:] - pathlen = len(path) - try: - index = path.index(c) - res += c + path[:index + 1] - except ValueError: - res += c + path - index = pathlen - 1 - elif c == percent: # variable or '%' - if path[index + 1:index + 2] == percent: - res += c - index += 1 - else: - path = path[index+1:] - pathlen = len(path) - try: - index = path.index(percent) - except ValueError: - res += percent + path - index = pathlen - 1 - else: - var = path[:index] - try: - if environ is None: - value = os.fsencode(os.environ[os.fsdecode(var)]) - else: - value = environ[var] - except KeyError: - value = percent + var + percent - res += value - elif c == dollar: # variable or '$$' - if path[index + 1:index + 2] == dollar: - res += c - index += 1 - elif path[index + 1:index + 2] == brace: - path = path[index+2:] - pathlen = len(path) - try: - index = path.index(rbrace) - except ValueError: - res += dollar + brace + path - index = pathlen - 1 - else: - var = path[:index] - try: - if environ is None: - value = os.fsencode(os.environ[os.fsdecode(var)]) - else: - value = environ[var] - except KeyError: - value = dollar + brace + var + rbrace - res += value - else: - var = path[:0] - index += 1 - c = path[index:index + 1] - while c and c in varchars: - var += c - index += 1 - c = path[index:index + 1] - try: - if environ is None: - value = os.fsencode(os.environ[os.fsdecode(var)]) - else: - value = environ[var] - except KeyError: - value = dollar + var - res += value - if c: - index -= 1 - else: - res += c - index += 1 - return res - - -# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. -# Previously, this function also truncated pathnames to 8+3 format, -# but as this module is called "ntpath", that's obviously wrong! - -def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'\\' - altsep = b'/' - curdir = b'.' - pardir = b'..' - special_prefixes = (b'\\\\.\\', b'\\\\?\\') - else: - sep = '\\' - altsep = '/' - curdir = '.' - pardir = '..' - special_prefixes = ('\\\\.\\', '\\\\?\\') - if path.startswith(special_prefixes): - # in the case of paths with these prefixes: - # \\.\ -> device names - # \\?\ -> literal paths - # do not do any normalization, but return the path unchanged - return path - path = path.replace(altsep, sep) - prefix, path = splitdrive(path) - - # collapse initial backslashes - if path.startswith(sep): - prefix += sep - path = path.lstrip(sep) - - comps = path.split(sep) - i = 0 - while i < len(comps): - if not comps[i] or comps[i] == curdir: - del comps[i] - elif comps[i] == pardir: - if i > 0 and comps[i-1] != pardir: - del comps[i-1:i+1] - i -= 1 - elif i == 0 and prefix.endswith(sep): - del comps[i] - else: - i += 1 - else: - i += 1 - # If the path is now empty, substitute '.' - if not prefix and not comps: - comps.append(curdir) - return prefix + sep.join(comps) - -def _abspath_fallback(path): - """Return the absolute version of a path as a fallback function in case - `nt._getfullpathname` is not available or raises OSError. See bpo-31047 for - more. - - """ - - path = os.fspath(path) - if not isabs(path): - if isinstance(path, bytes): - cwd = os.getcwdb() - else: - cwd = os.getcwd() - path = join(cwd, path) - return normpath(path) - -# Return an absolute path. -try: - from nt import _getfullpathname - -except ImportError: # not running on Windows - mock up something sensible - abspath = _abspath_fallback - -else: # use native Windows method on Windows - def abspath(path): - """Return the absolute version of a path.""" - try: - return normpath(_getfullpathname(path)) - except (OSError, ValueError): - return _abspath_fallback(path) - -# realpath is a no-op on systems without islink support -realpath = abspath -# Win9x family and earlier have no Unicode filename support. -supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and - sys.getwindowsversion()[3] >= 2) - -def relpath(path, start=None): - """Return a relative version of a path""" - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'\\' - curdir = b'.' - pardir = b'..' - else: - sep = '\\' - curdir = '.' - pardir = '..' - - if start is None: - start = curdir - - if not path: - raise ValueError("no path specified") - - start = os.fspath(start) - try: - start_abs = abspath(normpath(start)) - path_abs = abspath(normpath(path)) - start_drive, start_rest = splitdrive(start_abs) - path_drive, path_rest = splitdrive(path_abs) - if normcase(start_drive) != normcase(path_drive): - raise ValueError("path is on mount %r, start on mount %r" % ( - path_drive, start_drive)) - - start_list = [x for x in start_rest.split(sep) if x] - path_list = [x for x in path_rest.split(sep) if x] - # Work out how much of the filepath is shared by start and path. - i = 0 - for e1, e2 in zip(start_list, path_list): - if normcase(e1) != normcase(e2): - break - i += 1 - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return curdir - return join(*rel_list) - except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning): - genericpath._check_arg_types('relpath', path, start) - raise - - -# Return the longest common sub-path of the sequence of paths given as input. -# The function is case-insensitive and 'separator-insensitive', i.e. if the -# only difference between two paths is the use of '\' versus '/' as separator, -# they are deemed to be equal. -# -# However, the returned path will have the standard '\' separator (even if the -# given paths had the alternative '/' separator) and will have the case of the -# first path given in the sequence. Additionally, any trailing separator is -# stripped from the returned path. - -def commonpath(paths): - """Given a sequence of path names, returns the longest common sub-path.""" - - if not paths: - raise ValueError('commonpath() arg is an empty sequence') - - paths = tuple(map(os.fspath, paths)) - if isinstance(paths[0], bytes): - sep = b'\\' - altsep = b'/' - curdir = b'.' - else: - sep = '\\' - altsep = '/' - curdir = '.' - - try: - drivesplits = [splitdrive(p.replace(altsep, sep).lower()) for p in paths] - split_paths = [p.split(sep) for d, p in drivesplits] - - try: - isabs, = set(p[:1] == sep for d, p in drivesplits) - except ValueError: - raise ValueError("Can't mix absolute and relative paths") from None - - # Check that all drive letters or UNC paths match. The check is made only - # now otherwise type errors for mixing strings and bytes would not be - # caught. - if len(set(d for d, p in drivesplits)) != 1: - raise ValueError("Paths don't have the same drive") - - drive, path = splitdrive(paths[0].replace(altsep, sep)) - common = path.split(sep) - common = [c for c in common if c and c != curdir] - - split_paths = [[c for c in s if c and c != curdir] for s in split_paths] - s1 = min(split_paths) - s2 = max(split_paths) - for i, c in enumerate(s1): - if c != s2[i]: - common = common[:i] - break - else: - common = common[:len(s1)] - - prefix = drive + sep if isabs else drive - return prefix + sep.join(common) - except (TypeError, AttributeError): - genericpath._check_arg_types('commonpath', *paths) - raise - - -# determine if two files are in fact the same file -try: - # GetFinalPathNameByHandle is available starting with Windows 6.0. - # Windows XP and non-Windows OS'es will mock _getfinalpathname. - if sys.getwindowsversion()[:2] >= (6, 0): - from nt import _getfinalpathname - else: - raise ImportError -except (AttributeError, ImportError): - # On Windows XP and earlier, two files are the same if their absolute - # pathnames are the same. - # Non-Windows operating systems fake this method with an XP - # approximation. - def _getfinalpathname(f): - return normcase(abspath(f)) - - -try: - # The genericpath.isdir implementation uses os.stat and checks the mode - # attribute to tell whether or not the path is a directory. - # This is overkill on Windows - just pass the path to GetFileAttributes - # and check the attribute from there. - from nt import _isdir as isdir -except ImportError: - # Use genericpath.isdir as imported above. - pass diff --git a/experiment/simulation/backend/venv/lib/python3.7/operator.py b/experiment/simulation/backend/venv/lib/python3.7/operator.py deleted file mode 100644 index 0e2e53e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/operator.py +++ /dev/null @@ -1,464 +0,0 @@ -""" -Operator Interface - -This module exports a set of functions corresponding to the intrinsic -operators of Python. For example, operator.add(x, y) is equivalent -to the expression x+y. The function names are those used for special -methods; variants without leading and trailing '__' are also provided -for convenience. - -This is the pure Python implementation of the module. -""" - -__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf', - 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand', - 'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul', - 'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', - 'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', - 'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod', - 'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', - 'setitem', 'sub', 'truediv', 'truth', 'xor'] - -from builtins import abs as _abs - - -# Comparison Operations *******************************************************# - -def lt(a, b): - "Same as a < b." - return a < b - -def le(a, b): - "Same as a <= b." - return a <= b - -def eq(a, b): - "Same as a == b." - return a == b - -def ne(a, b): - "Same as a != b." - return a != b - -def ge(a, b): - "Same as a >= b." - return a >= b - -def gt(a, b): - "Same as a > b." - return a > b - -# Logical Operations **********************************************************# - -def not_(a): - "Same as not a." - return not a - -def truth(a): - "Return True if a is true, False otherwise." - return True if a else False - -def is_(a, b): - "Same as a is b." - return a is b - -def is_not(a, b): - "Same as a is not b." - return a is not b - -# Mathematical/Bitwise Operations *********************************************# - -def abs(a): - "Same as abs(a)." - return _abs(a) - -def add(a, b): - "Same as a + b." - return a + b - -def and_(a, b): - "Same as a & b." - return a & b - -def floordiv(a, b): - "Same as a // b." - return a // b - -def index(a): - "Same as a.__index__()." - return a.__index__() - -def inv(a): - "Same as ~a." - return ~a -invert = inv - -def lshift(a, b): - "Same as a << b." - return a << b - -def mod(a, b): - "Same as a % b." - return a % b - -def mul(a, b): - "Same as a * b." - return a * b - -def matmul(a, b): - "Same as a @ b." - return a @ b - -def neg(a): - "Same as -a." - return -a - -def or_(a, b): - "Same as a | b." - return a | b - -def pos(a): - "Same as +a." - return +a - -def pow(a, b): - "Same as a ** b." - return a ** b - -def rshift(a, b): - "Same as a >> b." - return a >> b - -def sub(a, b): - "Same as a - b." - return a - b - -def truediv(a, b): - "Same as a / b." - return a / b - -def xor(a, b): - "Same as a ^ b." - return a ^ b - -# Sequence Operations *********************************************************# - -def concat(a, b): - "Same as a + b, for a and b sequences." - if not hasattr(a, '__getitem__'): - msg = "'%s' object can't be concatenated" % type(a).__name__ - raise TypeError(msg) - return a + b - -def contains(a, b): - "Same as b in a (note reversed operands)." - return b in a - -def countOf(a, b): - "Return the number of times b occurs in a." - count = 0 - for i in a: - if i == b: - count += 1 - return count - -def delitem(a, b): - "Same as del a[b]." - del a[b] - -def getitem(a, b): - "Same as a[b]." - return a[b] - -def indexOf(a, b): - "Return the first index of b in a." - for i, j in enumerate(a): - if j == b: - return i - else: - raise ValueError('sequence.index(x): x not in sequence') - -def setitem(a, b, c): - "Same as a[b] = c." - a[b] = c - -def length_hint(obj, default=0): - """ - Return an estimate of the number of items in obj. - This is useful for presizing containers when building from an iterable. - - If the object supports len(), the result will be exact. Otherwise, it may - over- or under-estimate by an arbitrary amount. The result will be an - integer >= 0. - """ - if not isinstance(default, int): - msg = ("'%s' object cannot be interpreted as an integer" % - type(default).__name__) - raise TypeError(msg) - - try: - return len(obj) - except TypeError: - pass - - try: - hint = type(obj).__length_hint__ - except AttributeError: - return default - - try: - val = hint(obj) - except TypeError: - return default - if val is NotImplemented: - return default - if not isinstance(val, int): - msg = ('__length_hint__ must be integer, not %s' % - type(val).__name__) - raise TypeError(msg) - if val < 0: - msg = '__length_hint__() should return >= 0' - raise ValueError(msg) - return val - -# Generalized Lookup Objects **************************************************# - -class attrgetter: - """ - Return a callable object that fetches the given attribute(s) from its operand. - After f = attrgetter('name'), the call f(r) returns r.name. - After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date). - After h = attrgetter('name.first', 'name.last'), the call h(r) returns - (r.name.first, r.name.last). - """ - __slots__ = ('_attrs', '_call') - - def __init__(self, attr, *attrs): - if not attrs: - if not isinstance(attr, str): - raise TypeError('attribute name must be a string') - self._attrs = (attr,) - names = attr.split('.') - def func(obj): - for name in names: - obj = getattr(obj, name) - return obj - self._call = func - else: - self._attrs = (attr,) + attrs - getters = tuple(map(attrgetter, self._attrs)) - def func(obj): - return tuple(getter(obj) for getter in getters) - self._call = func - - def __call__(self, obj): - return self._call(obj) - - def __repr__(self): - return '%s.%s(%s)' % (self.__class__.__module__, - self.__class__.__qualname__, - ', '.join(map(repr, self._attrs))) - - def __reduce__(self): - return self.__class__, self._attrs - -class itemgetter: - """ - Return a callable object that fetches the given item(s) from its operand. - After f = itemgetter(2), the call f(r) returns r[2]. - After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) - """ - __slots__ = ('_items', '_call') - - def __init__(self, item, *items): - if not items: - self._items = (item,) - def func(obj): - return obj[item] - self._call = func - else: - self._items = items = (item,) + items - def func(obj): - return tuple(obj[i] for i in items) - self._call = func - - def __call__(self, obj): - return self._call(obj) - - def __repr__(self): - return '%s.%s(%s)' % (self.__class__.__module__, - self.__class__.__name__, - ', '.join(map(repr, self._items))) - - def __reduce__(self): - return self.__class__, self._items - -class methodcaller: - """ - Return a callable object that calls the given method on its operand. - After f = methodcaller('name'), the call f(r) returns r.name(). - After g = methodcaller('name', 'date', foo=1), the call g(r) returns - r.name('date', foo=1). - """ - __slots__ = ('_name', '_args', '_kwargs') - - def __init__(*args, **kwargs): - if len(args) < 2: - msg = "methodcaller needs at least one argument, the method name" - raise TypeError(msg) - self = args[0] - self._name = args[1] - if not isinstance(self._name, str): - raise TypeError('method name must be a string') - self._args = args[2:] - self._kwargs = kwargs - - def __call__(self, obj): - return getattr(obj, self._name)(*self._args, **self._kwargs) - - def __repr__(self): - args = [repr(self._name)] - args.extend(map(repr, self._args)) - args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items()) - return '%s.%s(%s)' % (self.__class__.__module__, - self.__class__.__name__, - ', '.join(args)) - - def __reduce__(self): - if not self._kwargs: - return self.__class__, (self._name,) + self._args - else: - from functools import partial - return partial(self.__class__, self._name, **self._kwargs), self._args - - -# In-place Operations *********************************************************# - -def iadd(a, b): - "Same as a += b." - a += b - return a - -def iand(a, b): - "Same as a &= b." - a &= b - return a - -def iconcat(a, b): - "Same as a += b, for a and b sequences." - if not hasattr(a, '__getitem__'): - msg = "'%s' object can't be concatenated" % type(a).__name__ - raise TypeError(msg) - a += b - return a - -def ifloordiv(a, b): - "Same as a //= b." - a //= b - return a - -def ilshift(a, b): - "Same as a <<= b." - a <<= b - return a - -def imod(a, b): - "Same as a %= b." - a %= b - return a - -def imul(a, b): - "Same as a *= b." - a *= b - return a - -def imatmul(a, b): - "Same as a @= b." - a @= b - return a - -def ior(a, b): - "Same as a |= b." - a |= b - return a - -def ipow(a, b): - "Same as a **= b." - a **=b - return a - -def irshift(a, b): - "Same as a >>= b." - a >>= b - return a - -def isub(a, b): - "Same as a -= b." - a -= b - return a - -def itruediv(a, b): - "Same as a /= b." - a /= b - return a - -def ixor(a, b): - "Same as a ^= b." - a ^= b - return a - - -try: - from _operator import * -except ImportError: - pass -else: - from _operator import __doc__ - -# All of these "__func__ = func" assignments have to happen after importing -# from _operator to make sure they're set to the right function -__lt__ = lt -__le__ = le -__eq__ = eq -__ne__ = ne -__ge__ = ge -__gt__ = gt -__not__ = not_ -__abs__ = abs -__add__ = add -__and__ = and_ -__floordiv__ = floordiv -__index__ = index -__inv__ = inv -__invert__ = invert -__lshift__ = lshift -__mod__ = mod -__mul__ = mul -__matmul__ = matmul -__neg__ = neg -__or__ = or_ -__pos__ = pos -__pow__ = pow -__rshift__ = rshift -__sub__ = sub -__truediv__ = truediv -__xor__ = xor -__concat__ = concat -__contains__ = contains -__delitem__ = delitem -__getitem__ = getitem -__setitem__ = setitem -__iadd__ = iadd -__iand__ = iand -__iconcat__ = iconcat -__ifloordiv__ = ifloordiv -__ilshift__ = ilshift -__imod__ = imod -__imul__ = imul -__imatmul__ = imatmul -__ior__ = ior -__ipow__ = ipow -__irshift__ = irshift -__isub__ = isub -__itruediv__ = itruediv -__ixor__ = ixor diff --git a/experiment/simulation/backend/venv/lib/python3.7/orig-prefix.txt b/experiment/simulation/backend/venv/lib/python3.7/orig-prefix.txt deleted file mode 100644 index e25db58..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/orig-prefix.txt +++ /dev/null @@ -1 +0,0 @@ -/usr \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/os.py b/experiment/simulation/backend/venv/lib/python3.7/os.py deleted file mode 100644 index 9853e37..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/os.py +++ /dev/null @@ -1,1083 +0,0 @@ -r"""OS routines for NT or Posix depending on what system we're on. - -This exports: - - all functions from posix or nt, e.g. unlink, stat, etc. - - os.path is either posixpath or ntpath - - os.name is either 'posix' or 'nt' - - os.curdir is a string representing the current directory (always '.') - - os.pardir is a string representing the parent directory (always '..') - - os.sep is the (or a most common) pathname separator ('/' or '\\') - - os.extsep is the extension separator (always '.') - - os.altsep is the alternate pathname separator (None or '/') - - os.pathsep is the component separator used in $PATH etc - - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') - - os.defpath is the default search path for executables - - os.devnull is the file path of the null device ('/dev/null', etc.) - -Programs that import and use 'os' stand a better chance of being -portable between different platforms. Of course, they must then -only use functions that are defined by all platforms (e.g., unlink -and opendir), and leave all pathname manipulation to os.path -(e.g., split and join). -""" - -#' -import abc -import sys -import stat as st - -from _collections_abc import _check_methods - -_names = sys.builtin_module_names - -# Note: more names are added to __all__ later. -__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", - "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", - "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen", - "popen", "extsep"] - -def _exists(name): - return name in globals() - -def _get_exports_list(module): - try: - return list(module.__all__) - except AttributeError: - return [n for n in dir(module) if n[0] != '_'] - -# Any new dependencies of the os module and/or changes in path separator -# requires updating importlib as well. -if 'posix' in _names: - name = 'posix' - linesep = '\n' - from posix import * - try: - from posix import _exit - __all__.append('_exit') - except ImportError: - pass - import posixpath as path - - try: - from posix import _have_functions - except ImportError: - pass - - import posix - __all__.extend(_get_exports_list(posix)) - del posix - -elif 'nt' in _names: - name = 'nt' - linesep = '\r\n' - from nt import * - try: - from nt import _exit - __all__.append('_exit') - except ImportError: - pass - import ntpath as path - - import nt - __all__.extend(_get_exports_list(nt)) - del nt - - try: - from nt import _have_functions - except ImportError: - pass - -else: - raise ImportError('no os specific module found') - -sys.modules['os.path'] = path -from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, - devnull) - -del _names - - -if _exists("_have_functions"): - _globals = globals() - def _add(str, fn): - if (fn in _globals) and (str in _have_functions): - _set.add(_globals[fn]) - - _set = set() - _add("HAVE_FACCESSAT", "access") - _add("HAVE_FCHMODAT", "chmod") - _add("HAVE_FCHOWNAT", "chown") - _add("HAVE_FSTATAT", "stat") - _add("HAVE_FUTIMESAT", "utime") - _add("HAVE_LINKAT", "link") - _add("HAVE_MKDIRAT", "mkdir") - _add("HAVE_MKFIFOAT", "mkfifo") - _add("HAVE_MKNODAT", "mknod") - _add("HAVE_OPENAT", "open") - _add("HAVE_READLINKAT", "readlink") - _add("HAVE_RENAMEAT", "rename") - _add("HAVE_SYMLINKAT", "symlink") - _add("HAVE_UNLINKAT", "unlink") - _add("HAVE_UNLINKAT", "rmdir") - _add("HAVE_UTIMENSAT", "utime") - supports_dir_fd = _set - - _set = set() - _add("HAVE_FACCESSAT", "access") - supports_effective_ids = _set - - _set = set() - _add("HAVE_FCHDIR", "chdir") - _add("HAVE_FCHMOD", "chmod") - _add("HAVE_FCHOWN", "chown") - _add("HAVE_FDOPENDIR", "listdir") - _add("HAVE_FDOPENDIR", "scandir") - _add("HAVE_FEXECVE", "execve") - _set.add(stat) # fstat always works - _add("HAVE_FTRUNCATE", "truncate") - _add("HAVE_FUTIMENS", "utime") - _add("HAVE_FUTIMES", "utime") - _add("HAVE_FPATHCONF", "pathconf") - if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3 - _add("HAVE_FSTATVFS", "statvfs") - supports_fd = _set - - _set = set() - _add("HAVE_FACCESSAT", "access") - # Some platforms don't support lchmod(). Often the function exists - # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP. - # (No, I don't know why that's a good design.) ./configure will detect - # this and reject it--so HAVE_LCHMOD still won't be defined on such - # platforms. This is Very Helpful. - # - # However, sometimes platforms without a working lchmod() *do* have - # fchmodat(). (Examples: Linux kernel 3.2 with glibc 2.15, - # OpenIndiana 3.x.) And fchmodat() has a flag that theoretically makes - # it behave like lchmod(). So in theory it would be a suitable - # replacement for lchmod(). But when lchmod() doesn't work, fchmodat()'s - # flag doesn't work *either*. Sadly ./configure isn't sophisticated - # enough to detect this condition--it only determines whether or not - # fchmodat() minimally works. - # - # Therefore we simply ignore fchmodat() when deciding whether or not - # os.chmod supports follow_symlinks. Just checking lchmod() is - # sufficient. After all--if you have a working fchmodat(), your - # lchmod() almost certainly works too. - # - # _add("HAVE_FCHMODAT", "chmod") - _add("HAVE_FCHOWNAT", "chown") - _add("HAVE_FSTATAT", "stat") - _add("HAVE_LCHFLAGS", "chflags") - _add("HAVE_LCHMOD", "chmod") - if _exists("lchown"): # mac os x10.3 - _add("HAVE_LCHOWN", "chown") - _add("HAVE_LINKAT", "link") - _add("HAVE_LUTIMES", "utime") - _add("HAVE_LSTAT", "stat") - _add("HAVE_FSTATAT", "stat") - _add("HAVE_UTIMENSAT", "utime") - _add("MS_WINDOWS", "stat") - supports_follow_symlinks = _set - - del _set - del _have_functions - del _globals - del _add - - -# Python uses fixed values for the SEEK_ constants; they are mapped -# to native constants if necessary in posixmodule.c -# Other possible SEEK values are directly imported from posixmodule.c -SEEK_SET = 0 -SEEK_CUR = 1 -SEEK_END = 2 - -# Super directory utilities. -# (Inspired by Eric Raymond; the doc strings are mostly his) - -def makedirs(name, mode=0o777, exist_ok=False): - """makedirs(name [, mode=0o777][, exist_ok=False]) - - Super-mkdir; create a leaf directory and all intermediate ones. Works like - mkdir, except that any intermediate path segment (not just the rightmost) - will be created if it does not exist. If the target directory already - exists, raise an OSError if exist_ok is False. Otherwise no exception is - raised. This is recursive. - - """ - head, tail = path.split(name) - if not tail: - head, tail = path.split(head) - if head and tail and not path.exists(head): - try: - makedirs(head, exist_ok=exist_ok) - except FileExistsError: - # Defeats race condition when another thread created the path - pass - cdir = curdir - if isinstance(tail, bytes): - cdir = bytes(curdir, 'ASCII') - if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists - return - try: - mkdir(name, mode) - except OSError: - # Cannot rely on checking for EEXIST, since the operating system - # could give priority to other errors like EACCES or EROFS - if not exist_ok or not path.isdir(name): - raise - -def removedirs(name): - """removedirs(name) - - Super-rmdir; remove a leaf directory and all empty intermediate - ones. Works like rmdir except that, if the leaf directory is - successfully removed, directories corresponding to rightmost path - segments will be pruned away until either the whole path is - consumed or an error occurs. Errors during this latter phase are - ignored -- they generally mean that a directory was not empty. - - """ - rmdir(name) - head, tail = path.split(name) - if not tail: - head, tail = path.split(head) - while head and tail: - try: - rmdir(head) - except OSError: - break - head, tail = path.split(head) - -def renames(old, new): - """renames(old, new) - - Super-rename; create directories as necessary and delete any left - empty. Works like rename, except creation of any intermediate - directories needed to make the new pathname good is attempted - first. After the rename, directories corresponding to rightmost - path segments of the old name will be pruned until either the - whole path is consumed or a nonempty directory is found. - - Note: this function can fail with the new directory structure made - if you lack permissions needed to unlink the leaf directory or - file. - - """ - head, tail = path.split(new) - if head and tail and not path.exists(head): - makedirs(head) - rename(old, new) - head, tail = path.split(old) - if head and tail: - try: - removedirs(head) - except OSError: - pass - -__all__.extend(["makedirs", "removedirs", "renames"]) - -def walk(top, topdown=True, onerror=None, followlinks=False): - """Directory tree generator. - - For each directory in the directory tree rooted at top (including top - itself, but excluding '.' and '..'), yields a 3-tuple - - dirpath, dirnames, filenames - - dirpath is a string, the path to the directory. dirnames is a list of - the names of the subdirectories in dirpath (excluding '.' and '..'). - filenames is a list of the names of the non-directory files in dirpath. - Note that the names in the lists are just names, with no path components. - To get a full path (which begins with top) to a file or directory in - dirpath, do os.path.join(dirpath, name). - - If optional arg 'topdown' is true or not specified, the triple for a - directory is generated before the triples for any of its subdirectories - (directories are generated top down). If topdown is false, the triple - for a directory is generated after the triples for all of its - subdirectories (directories are generated bottom up). - - When topdown is true, the caller can modify the dirnames list in-place - (e.g., via del or slice assignment), and walk will only recurse into the - subdirectories whose names remain in dirnames; this can be used to prune the - search, or to impose a specific order of visiting. Modifying dirnames when - topdown is false has no effect on the behavior of os.walk(), since the - directories in dirnames have already been generated by the time dirnames - itself is generated. No matter the value of topdown, the list of - subdirectories is retrieved before the tuples for the directory and its - subdirectories are generated. - - By default errors from the os.scandir() call are ignored. If - optional arg 'onerror' is specified, it should be a function; it - will be called with one argument, an OSError instance. It can - report the error to continue with the walk, or raise the exception - to abort the walk. Note that the filename is available as the - filename attribute of the exception object. - - By default, os.walk does not follow symbolic links to subdirectories on - systems that support them. In order to get this functionality, set the - optional argument 'followlinks' to true. - - Caution: if you pass a relative pathname for top, don't change the - current working directory between resumptions of walk. walk never - changes the current directory, and assumes that the client doesn't - either. - - Example: - - import os - from os.path import join, getsize - for root, dirs, files in os.walk('python/Lib/email'): - print(root, "consumes", end="") - print(sum([getsize(join(root, name)) for name in files]), end="") - print("bytes in", len(files), "non-directory files") - if 'CVS' in dirs: - dirs.remove('CVS') # don't visit CVS directories - - """ - top = fspath(top) - dirs = [] - nondirs = [] - walk_dirs = [] - - # We may not have read permission for top, in which case we can't - # get a list of the files the directory contains. os.walk - # always suppressed the exception then, rather than blow up for a - # minor reason when (say) a thousand readable directories are still - # left to visit. That logic is copied here. - try: - # Note that scandir is global in this module due - # to earlier import-*. - scandir_it = scandir(top) - except OSError as error: - if onerror is not None: - onerror(error) - return - - with scandir_it: - while True: - try: - try: - entry = next(scandir_it) - except StopIteration: - break - except OSError as error: - if onerror is not None: - onerror(error) - return - - try: - is_dir = entry.is_dir() - except OSError: - # If is_dir() raises an OSError, consider that the entry is not - # a directory, same behaviour than os.path.isdir(). - is_dir = False - - if is_dir: - dirs.append(entry.name) - else: - nondirs.append(entry.name) - - if not topdown and is_dir: - # Bottom-up: recurse into sub-directory, but exclude symlinks to - # directories if followlinks is False - if followlinks: - walk_into = True - else: - try: - is_symlink = entry.is_symlink() - except OSError: - # If is_symlink() raises an OSError, consider that the - # entry is not a symbolic link, same behaviour than - # os.path.islink(). - is_symlink = False - walk_into = not is_symlink - - if walk_into: - walk_dirs.append(entry.path) - - # Yield before recursion if going top down - if topdown: - yield top, dirs, nondirs - - # Recurse into sub-directories - islink, join = path.islink, path.join - for dirname in dirs: - new_path = join(top, dirname) - # Issue #23605: os.path.islink() is used instead of caching - # entry.is_symlink() result during the loop on os.scandir() because - # the caller can replace the directory entry during the "yield" - # above. - if followlinks or not islink(new_path): - yield from walk(new_path, topdown, onerror, followlinks) - else: - # Recurse into sub-directories - for new_path in walk_dirs: - yield from walk(new_path, topdown, onerror, followlinks) - # Yield after recursion if going bottom up - yield top, dirs, nondirs - -__all__.append("walk") - -if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: - - def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): - """Directory tree generator. - - This behaves exactly like walk(), except that it yields a 4-tuple - - dirpath, dirnames, filenames, dirfd - - `dirpath`, `dirnames` and `filenames` are identical to walk() output, - and `dirfd` is a file descriptor referring to the directory `dirpath`. - - The advantage of fwalk() over walk() is that it's safe against symlink - races (when follow_symlinks is False). - - If dir_fd is not None, it should be a file descriptor open to a directory, - and top should be relative; top will then be relative to that directory. - (dir_fd is always supported for fwalk.) - - Caution: - Since fwalk() yields file descriptors, those are only valid until the - next iteration step, so you should dup() them if you want to keep them - for a longer period. - - Example: - - import os - for root, dirs, files, rootfd in os.fwalk('python/Lib/email'): - print(root, "consumes", end="") - print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]), - end="") - print("bytes in", len(files), "non-directory files") - if 'CVS' in dirs: - dirs.remove('CVS') # don't visit CVS directories - """ - if not isinstance(top, int) or not hasattr(top, '__index__'): - top = fspath(top) - # Note: To guard against symlink races, we use the standard - # lstat()/open()/fstat() trick. - if not follow_symlinks: - orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) - topfd = open(top, O_RDONLY, dir_fd=dir_fd) - try: - if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and - path.samestat(orig_st, stat(topfd)))): - yield from _fwalk(topfd, top, isinstance(top, bytes), - topdown, onerror, follow_symlinks) - finally: - close(topfd) - - def _fwalk(topfd, toppath, isbytes, topdown, onerror, follow_symlinks): - # Note: This uses O(depth of the directory tree) file descriptors: if - # necessary, it can be adapted to only require O(1) FDs, see issue - # #13734. - - scandir_it = scandir(topfd) - dirs = [] - nondirs = [] - entries = None if topdown or follow_symlinks else [] - for entry in scandir_it: - name = entry.name - if isbytes: - name = fsencode(name) - try: - if entry.is_dir(): - dirs.append(name) - if entries is not None: - entries.append(entry) - else: - nondirs.append(name) - except OSError: - try: - # Add dangling symlinks, ignore disappeared files - if entry.is_symlink(): - nondirs.append(name) - except OSError: - pass - - if topdown: - yield toppath, dirs, nondirs, topfd - - for name in dirs if entries is None else zip(dirs, entries): - try: - if not follow_symlinks: - if topdown: - orig_st = stat(name, dir_fd=topfd, follow_symlinks=False) - else: - assert entries is not None - name, entry = name - orig_st = entry.stat(follow_symlinks=False) - dirfd = open(name, O_RDONLY, dir_fd=topfd) - except OSError as err: - if onerror is not None: - onerror(err) - continue - try: - if follow_symlinks or path.samestat(orig_st, stat(dirfd)): - dirpath = path.join(toppath, name) - yield from _fwalk(dirfd, dirpath, isbytes, - topdown, onerror, follow_symlinks) - finally: - close(dirfd) - - if not topdown: - yield toppath, dirs, nondirs, topfd - - __all__.append("fwalk") - -# Make sure os.environ exists, at least -try: - environ -except NameError: - environ = {} - -def execl(file, *args): - """execl(file, *args) - - Execute the executable file with argument list args, replacing the - current process. """ - execv(file, args) - -def execle(file, *args): - """execle(file, *args, env) - - Execute the executable file with argument list args and - environment env, replacing the current process. """ - env = args[-1] - execve(file, args[:-1], env) - -def execlp(file, *args): - """execlp(file, *args) - - Execute the executable file (which is searched for along $PATH) - with argument list args, replacing the current process. """ - execvp(file, args) - -def execlpe(file, *args): - """execlpe(file, *args, env) - - Execute the executable file (which is searched for along $PATH) - with argument list args and environment env, replacing the current - process. """ - env = args[-1] - execvpe(file, args[:-1], env) - -def execvp(file, args): - """execvp(file, args) - - Execute the executable file (which is searched for along $PATH) - with argument list args, replacing the current process. - args may be a list or tuple of strings. """ - _execvpe(file, args) - -def execvpe(file, args, env): - """execvpe(file, args, env) - - Execute the executable file (which is searched for along $PATH) - with argument list args and environment env, replacing the - current process. - args may be a list or tuple of strings. """ - _execvpe(file, args, env) - -__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) - -def _execvpe(file, args, env=None): - if env is not None: - exec_func = execve - argrest = (args, env) - else: - exec_func = execv - argrest = (args,) - env = environ - - if path.dirname(file): - exec_func(file, *argrest) - return - saved_exc = None - path_list = get_exec_path(env) - if name != 'nt': - file = fsencode(file) - path_list = map(fsencode, path_list) - for dir in path_list: - fullname = path.join(dir, file) - try: - exec_func(fullname, *argrest) - except (FileNotFoundError, NotADirectoryError) as e: - last_exc = e - except OSError as e: - last_exc = e - if saved_exc is None: - saved_exc = e - if saved_exc is not None: - raise saved_exc - raise last_exc - - -def get_exec_path(env=None): - """Returns the sequence of directories that will be searched for the - named executable (similar to a shell) when launching a process. - - *env* must be an environment variable dict or None. If *env* is None, - os.environ will be used. - """ - # Use a local import instead of a global import to limit the number of - # modules loaded at startup: the os module is always loaded at startup by - # Python. It may also avoid a bootstrap issue. - import warnings - - if env is None: - env = environ - - # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a - # BytesWarning when using python -b or python -bb: ignore the warning - with warnings.catch_warnings(): - warnings.simplefilter("ignore", BytesWarning) - - try: - path_list = env.get('PATH') - except TypeError: - path_list = None - - if supports_bytes_environ: - try: - path_listb = env[b'PATH'] - except (KeyError, TypeError): - pass - else: - if path_list is not None: - raise ValueError( - "env cannot contain 'PATH' and b'PATH' keys") - path_list = path_listb - - if path_list is not None and isinstance(path_list, bytes): - path_list = fsdecode(path_list) - - if path_list is None: - path_list = defpath - return path_list.split(pathsep) - - -# Change environ to automatically call putenv(), unsetenv if they exist. -from _collections_abc import MutableMapping - -class _Environ(MutableMapping): - def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv): - self.encodekey = encodekey - self.decodekey = decodekey - self.encodevalue = encodevalue - self.decodevalue = decodevalue - self.putenv = putenv - self.unsetenv = unsetenv - self._data = data - - def __getitem__(self, key): - try: - value = self._data[self.encodekey(key)] - except KeyError: - # raise KeyError with the original key value - raise KeyError(key) from None - return self.decodevalue(value) - - def __setitem__(self, key, value): - key = self.encodekey(key) - value = self.encodevalue(value) - self.putenv(key, value) - self._data[key] = value - - def __delitem__(self, key): - encodedkey = self.encodekey(key) - self.unsetenv(encodedkey) - try: - del self._data[encodedkey] - except KeyError: - # raise KeyError with the original key value - raise KeyError(key) from None - - def __iter__(self): - # list() from dict object is an atomic operation - keys = list(self._data) - for key in keys: - yield self.decodekey(key) - - def __len__(self): - return len(self._data) - - def __repr__(self): - return 'environ({{{}}})'.format(', '.join( - ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value)) - for key, value in self._data.items()))) - - def copy(self): - return dict(self) - - def setdefault(self, key, value): - if key not in self: - self[key] = value - return self[key] - -try: - _putenv = putenv -except NameError: - _putenv = lambda key, value: None -else: - if "putenv" not in __all__: - __all__.append("putenv") - -try: - _unsetenv = unsetenv -except NameError: - _unsetenv = lambda key: _putenv(key, "") -else: - if "unsetenv" not in __all__: - __all__.append("unsetenv") - -def _createenviron(): - if name == 'nt': - # Where Env Var Names Must Be UPPERCASE - def check_str(value): - if not isinstance(value, str): - raise TypeError("str expected, not %s" % type(value).__name__) - return value - encode = check_str - decode = str - def encodekey(key): - return encode(key).upper() - data = {} - for key, value in environ.items(): - data[encodekey(key)] = value - else: - # Where Env Var Names Can Be Mixed Case - encoding = sys.getfilesystemencoding() - def encode(value): - if not isinstance(value, str): - raise TypeError("str expected, not %s" % type(value).__name__) - return value.encode(encoding, 'surrogateescape') - def decode(value): - return value.decode(encoding, 'surrogateescape') - encodekey = encode - data = environ - return _Environ(data, - encodekey, decode, - encode, decode, - _putenv, _unsetenv) - -# unicode environ -environ = _createenviron() -del _createenviron - - -def getenv(key, default=None): - """Get an environment variable, return None if it doesn't exist. - The optional second argument can specify an alternate default. - key, default and the result are str.""" - return environ.get(key, default) - -supports_bytes_environ = (name != 'nt') -__all__.extend(("getenv", "supports_bytes_environ")) - -if supports_bytes_environ: - def _check_bytes(value): - if not isinstance(value, bytes): - raise TypeError("bytes expected, not %s" % type(value).__name__) - return value - - # bytes environ - environb = _Environ(environ._data, - _check_bytes, bytes, - _check_bytes, bytes, - _putenv, _unsetenv) - del _check_bytes - - def getenvb(key, default=None): - """Get an environment variable, return None if it doesn't exist. - The optional second argument can specify an alternate default. - key, default and the result are bytes.""" - return environb.get(key, default) - - __all__.extend(("environb", "getenvb")) - -def _fscodec(): - encoding = sys.getfilesystemencoding() - errors = sys.getfilesystemencodeerrors() - - def fsencode(filename): - """Encode filename (an os.PathLike, bytes, or str) to the filesystem - encoding with 'surrogateescape' error handler, return bytes unchanged. - On Windows, use 'strict' error handler if the file system encoding is - 'mbcs' (which is the default encoding). - """ - filename = fspath(filename) # Does type-checking of `filename`. - if isinstance(filename, str): - return filename.encode(encoding, errors) - else: - return filename - - def fsdecode(filename): - """Decode filename (an os.PathLike, bytes, or str) from the filesystem - encoding with 'surrogateescape' error handler, return str unchanged. On - Windows, use 'strict' error handler if the file system encoding is - 'mbcs' (which is the default encoding). - """ - filename = fspath(filename) # Does type-checking of `filename`. - if isinstance(filename, bytes): - return filename.decode(encoding, errors) - else: - return filename - - return fsencode, fsdecode - -fsencode, fsdecode = _fscodec() -del _fscodec - -# Supply spawn*() (probably only for Unix) -if _exists("fork") and not _exists("spawnv") and _exists("execv"): - - P_WAIT = 0 - P_NOWAIT = P_NOWAITO = 1 - - __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"]) - - # XXX Should we support P_DETACH? I suppose it could fork()**2 - # and close the std I/O streams. Also, P_OVERLAY is the same - # as execv*()? - - def _spawnvef(mode, file, args, env, func): - # Internal helper; func is the exec*() function to use - if not isinstance(args, (tuple, list)): - raise TypeError('argv must be a tuple or a list') - if not args or not args[0]: - raise ValueError('argv first element cannot be empty') - pid = fork() - if not pid: - # Child - try: - if env is None: - func(file, args) - else: - func(file, args, env) - except: - _exit(127) - else: - # Parent - if mode == P_NOWAIT: - return pid # Caller is responsible for waiting! - while 1: - wpid, sts = waitpid(pid, 0) - if WIFSTOPPED(sts): - continue - elif WIFSIGNALED(sts): - return -WTERMSIG(sts) - elif WIFEXITED(sts): - return WEXITSTATUS(sts) - else: - raise OSError("Not stopped, signaled or exited???") - - def spawnv(mode, file, args): - """spawnv(mode, file, args) -> integer - -Execute file with arguments from args in a subprocess. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return _spawnvef(mode, file, args, None, execv) - - def spawnve(mode, file, args, env): - """spawnve(mode, file, args, env) -> integer - -Execute file with arguments from args in a subprocess with the -specified environment. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return _spawnvef(mode, file, args, env, execve) - - # Note: spawnvp[e] isn't currently supported on Windows - - def spawnvp(mode, file, args): - """spawnvp(mode, file, args) -> integer - -Execute file (which is looked for along $PATH) with arguments from -args in a subprocess. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return _spawnvef(mode, file, args, None, execvp) - - def spawnvpe(mode, file, args, env): - """spawnvpe(mode, file, args, env) -> integer - -Execute file (which is looked for along $PATH) with arguments from -args in a subprocess with the supplied environment. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return _spawnvef(mode, file, args, env, execvpe) - - - __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"]) - - -if _exists("spawnv"): - # These aren't supplied by the basic Windows code - # but can be easily implemented in Python - - def spawnl(mode, file, *args): - """spawnl(mode, file, *args) -> integer - -Execute file with arguments from args in a subprocess. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return spawnv(mode, file, args) - - def spawnle(mode, file, *args): - """spawnle(mode, file, *args, env) -> integer - -Execute file with arguments from args in a subprocess with the -supplied environment. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - env = args[-1] - return spawnve(mode, file, args[:-1], env) - - - __all__.extend(["spawnl", "spawnle"]) - - -if _exists("spawnvp"): - # At the moment, Windows doesn't implement spawnvp[e], - # so it won't have spawnlp[e] either. - def spawnlp(mode, file, *args): - """spawnlp(mode, file, *args) -> integer - -Execute file (which is looked for along $PATH) with arguments from -args in a subprocess with the supplied environment. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - return spawnvp(mode, file, args) - - def spawnlpe(mode, file, *args): - """spawnlpe(mode, file, *args, env) -> integer - -Execute file (which is looked for along $PATH) with arguments from -args in a subprocess with the supplied environment. -If mode == P_NOWAIT return the pid of the process. -If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ - env = args[-1] - return spawnvpe(mode, file, args[:-1], env) - - - __all__.extend(["spawnlp", "spawnlpe"]) - - -# Supply os.popen() -def popen(cmd, mode="r", buffering=-1): - if not isinstance(cmd, str): - raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) - if mode not in ("r", "w"): - raise ValueError("invalid mode %r" % mode) - if buffering == 0 or buffering is None: - raise ValueError("popen() does not support unbuffered streams") - import subprocess, io - if mode == "r": - proc = subprocess.Popen(cmd, - shell=True, - stdout=subprocess.PIPE, - bufsize=buffering) - return _wrap_close(io.TextIOWrapper(proc.stdout), proc) - else: - proc = subprocess.Popen(cmd, - shell=True, - stdin=subprocess.PIPE, - bufsize=buffering) - return _wrap_close(io.TextIOWrapper(proc.stdin), proc) - -# Helper for popen() -- a proxy for a file whose close waits for the process -class _wrap_close: - def __init__(self, stream, proc): - self._stream = stream - self._proc = proc - def close(self): - self._stream.close() - returncode = self._proc.wait() - if returncode == 0: - return None - if name == 'nt': - return returncode - else: - return returncode << 8 # Shift left to match old behavior - def __enter__(self): - return self - def __exit__(self, *args): - self.close() - def __getattr__(self, name): - return getattr(self._stream, name) - def __iter__(self): - return iter(self._stream) - -# Supply os.fdopen() -def fdopen(fd, *args, **kwargs): - if not isinstance(fd, int): - raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) - import io - return io.open(fd, *args, **kwargs) - - -# For testing purposes, make sure the function is available when the C -# implementation exists. -def _fspath(path): - """Return the path representation of a path-like object. - - If str or bytes is passed in, it is returned unchanged. Otherwise the - os.PathLike interface is used to get the path representation. If the - path representation is not str or bytes, TypeError is raised. If the - provided path is not str, bytes, or os.PathLike, TypeError is raised. - """ - if isinstance(path, (str, bytes)): - return path - - # Work from the object's type to match method resolution of other magic - # methods. - path_type = type(path) - try: - path_repr = path_type.__fspath__(path) - except AttributeError: - if hasattr(path_type, '__fspath__'): - raise - else: - raise TypeError("expected str, bytes or os.PathLike object, " - "not " + path_type.__name__) - if isinstance(path_repr, (str, bytes)): - return path_repr - else: - raise TypeError("expected {}.__fspath__() to return str or bytes, " - "not {}".format(path_type.__name__, - type(path_repr).__name__)) - -# If there is no C implementation, make the pure Python version the -# implementation as transparently as possible. -if not _exists('fspath'): - fspath = _fspath - fspath.__name__ = "fspath" - - -class PathLike(abc.ABC): - - """Abstract base class for implementing the file system path protocol.""" - - @abc.abstractmethod - def __fspath__(self): - """Return the file system path representation of the object.""" - raise NotImplementedError - - @classmethod - def __subclasshook__(cls, subclass): - if cls is PathLike: - return _check_methods(subclass, '__fspath__') - return NotImplemented diff --git a/experiment/simulation/backend/venv/lib/python3.7/posixpath.py b/experiment/simulation/backend/venv/lib/python3.7/posixpath.py deleted file mode 100644 index 785aa72..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/posixpath.py +++ /dev/null @@ -1,529 +0,0 @@ -"""Common operations on Posix pathnames. - -Instead of importing this module directly, import os and refer to -this module as os.path. The "os.path" name is an alias for this -module on Posix systems; on other systems (e.g. Mac, Windows), -os.path provides the same operations in a manner specific to that -platform, and is an alias to another module (e.g. macpath, ntpath). - -Some of this can actually be useful on non-Posix systems too, e.g. -for manipulation of the pathname component of URLs. -""" - -# Strings representing various path-related bits and pieces. -# These are primarily for export; internally, they are hardcoded. -# Should be set before imports for resolving cyclic dependency. -curdir = '.' -pardir = '..' -extsep = '.' -sep = '/' -pathsep = ':' -defpath = '/bin:/usr/bin' -altsep = None -devnull = '/dev/null' - -import os -import sys -import stat -import genericpath -from genericpath import * - -__all__ = ["normcase","isabs","join","splitdrive","split","splitext", - "basename","dirname","commonprefix","getsize","getmtime", - "getatime","getctime","islink","exists","lexists","isdir","isfile", - "ismount", "expanduser","expandvars","normpath","abspath", - "samefile","sameopenfile","samestat", - "curdir","pardir","sep","pathsep","defpath","altsep","extsep", - "devnull","realpath","supports_unicode_filenames","relpath", - "commonpath"] - - -def _get_sep(path): - if isinstance(path, bytes): - return b'/' - else: - return '/' - -# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. -# On MS-DOS this may also turn slashes into backslashes; however, other -# normalizations (such as optimizing '../' away) are not allowed -# (another function should be defined to do that). - -def normcase(s): - """Normalize case of pathname. Has no effect under Posix""" - s = os.fspath(s) - if not isinstance(s, (bytes, str)): - raise TypeError("normcase() argument must be str or bytes, " - "not '{}'".format(s.__class__.__name__)) - return s - - -# Return whether a path is absolute. -# Trivial in Posix, harder on the Mac or MS-DOS. - -def isabs(s): - """Test whether a path is absolute""" - s = os.fspath(s) - sep = _get_sep(s) - return s.startswith(sep) - - -# Join pathnames. -# Ignore the previous parts if a part is absolute. -# Insert a '/' unless the first part is empty or already ends in '/'. - -def join(a, *p): - """Join two or more pathname components, inserting '/' as needed. - If any component is an absolute path, all previous path components - will be discarded. An empty last part will result in a path that - ends with a separator.""" - a = os.fspath(a) - sep = _get_sep(a) - path = a - try: - if not p: - path[:0] + sep #23780: Ensure compatible data type even if p is null. - for b in map(os.fspath, p): - if b.startswith(sep): - path = b - elif not path or path.endswith(sep): - path += b - else: - path += sep + b - except (TypeError, AttributeError, BytesWarning): - genericpath._check_arg_types('join', a, *p) - raise - return path - - -# Split a path in head (everything up to the last '/') and tail (the -# rest). If the path ends in '/', tail will be empty. If there is no -# '/' in the path, head will be empty. -# Trailing '/'es are stripped from head unless it is the root. - -def split(p): - """Split a pathname. Returns tuple "(head, tail)" where "tail" is - everything after the final slash. Either part may be empty.""" - p = os.fspath(p) - sep = _get_sep(p) - i = p.rfind(sep) + 1 - head, tail = p[:i], p[i:] - if head and head != sep*len(head): - head = head.rstrip(sep) - return head, tail - - -# Split a path in root and extension. -# The extension is everything starting at the last dot in the last -# pathname component; the root is everything before that. -# It is always true that root + ext == p. - -def splitext(p): - p = os.fspath(p) - if isinstance(p, bytes): - sep = b'/' - extsep = b'.' - else: - sep = '/' - extsep = '.' - return genericpath._splitext(p, sep, None, extsep) -splitext.__doc__ = genericpath._splitext.__doc__ - -# Split a pathname into a drive specification and the rest of the -# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. - -def splitdrive(p): - """Split a pathname into drive and path. On Posix, drive is always - empty.""" - p = os.fspath(p) - return p[:0], p - - -# Return the tail (basename) part of a path, same as split(path)[1]. - -def basename(p): - """Returns the final component of a pathname""" - p = os.fspath(p) - sep = _get_sep(p) - i = p.rfind(sep) + 1 - return p[i:] - - -# Return the head (dirname) part of a path, same as split(path)[0]. - -def dirname(p): - """Returns the directory component of a pathname""" - p = os.fspath(p) - sep = _get_sep(p) - i = p.rfind(sep) + 1 - head = p[:i] - if head and head != sep*len(head): - head = head.rstrip(sep) - return head - - -# Is a path a symbolic link? -# This will always return false on systems where os.lstat doesn't exist. - -def islink(path): - """Test whether a path is a symbolic link""" - try: - st = os.lstat(path) - except (OSError, AttributeError): - return False - return stat.S_ISLNK(st.st_mode) - -# Being true for dangling symbolic links is also useful. - -def lexists(path): - """Test whether a path exists. Returns True for broken symbolic links""" - try: - os.lstat(path) - except OSError: - return False - return True - - -# Is a path a mount point? -# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) - -def ismount(path): - """Test whether a path is a mount point""" - try: - s1 = os.lstat(path) - except OSError: - # It doesn't exist -- so not a mount point. :-) - return False - else: - # A symlink can never be a mount point - if stat.S_ISLNK(s1.st_mode): - return False - - if isinstance(path, bytes): - parent = join(path, b'..') - else: - parent = join(path, '..') - parent = realpath(parent) - try: - s2 = os.lstat(parent) - except OSError: - return False - - dev1 = s1.st_dev - dev2 = s2.st_dev - if dev1 != dev2: - return True # path/.. on a different device as path - ino1 = s1.st_ino - ino2 = s2.st_ino - if ino1 == ino2: - return True # path/.. is the same i-node as path - return False - - -# Expand paths beginning with '~' or '~user'. -# '~' means $HOME; '~user' means that user's home directory. -# If the path doesn't begin with '~', or if the user or $HOME is unknown, -# the path is returned unchanged (leaving error reporting to whatever -# function is called with the expanded path as argument). -# See also module 'glob' for expansion of *, ? and [...] in pathnames. -# (A function should also be defined to do full *sh-style environment -# variable expansion.) - -def expanduser(path): - """Expand ~ and ~user constructions. If user or $HOME is unknown, - do nothing.""" - path = os.fspath(path) - if isinstance(path, bytes): - tilde = b'~' - else: - tilde = '~' - if not path.startswith(tilde): - return path - sep = _get_sep(path) - i = path.find(sep, 1) - if i < 0: - i = len(path) - if i == 1: - if 'HOME' not in os.environ: - import pwd - try: - userhome = pwd.getpwuid(os.getuid()).pw_dir - except KeyError: - # bpo-10496: if the current user identifier doesn't exist in the - # password database, return the path unchanged - return path - else: - userhome = os.environ['HOME'] - else: - import pwd - name = path[1:i] - if isinstance(name, bytes): - name = str(name, 'ASCII') - try: - pwent = pwd.getpwnam(name) - except KeyError: - # bpo-10496: if the user name from the path doesn't exist in the - # password database, return the path unchanged - return path - userhome = pwent.pw_dir - if isinstance(path, bytes): - userhome = os.fsencode(userhome) - root = b'/' - else: - root = '/' - userhome = userhome.rstrip(root) - return (userhome + path[i:]) or root - - -# Expand paths containing shell variable substitutions. -# This expands the forms $variable and ${variable} only. -# Non-existent variables are left unchanged. - -_varprog = None -_varprogb = None - -def expandvars(path): - """Expand shell variables of form $var and ${var}. Unknown variables - are left unchanged.""" - path = os.fspath(path) - global _varprog, _varprogb - if isinstance(path, bytes): - if b'$' not in path: - return path - if not _varprogb: - import re - _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) - search = _varprogb.search - start = b'{' - end = b'}' - environ = getattr(os, 'environb', None) - else: - if '$' not in path: - return path - if not _varprog: - import re - _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) - search = _varprog.search - start = '{' - end = '}' - environ = os.environ - i = 0 - while True: - m = search(path, i) - if not m: - break - i, j = m.span(0) - name = m.group(1) - if name.startswith(start) and name.endswith(end): - name = name[1:-1] - try: - if environ is None: - value = os.fsencode(os.environ[os.fsdecode(name)]) - else: - value = environ[name] - except KeyError: - i = j - else: - tail = path[j:] - path = path[:i] + value - i = len(path) - path += tail - return path - - -# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. -# It should be understood that this may change the meaning of the path -# if it contains symbolic links! - -def normpath(path): - """Normalize path, eliminating double slashes, etc.""" - path = os.fspath(path) - if isinstance(path, bytes): - sep = b'/' - empty = b'' - dot = b'.' - dotdot = b'..' - else: - sep = '/' - empty = '' - dot = '.' - dotdot = '..' - if path == empty: - return dot - initial_slashes = path.startswith(sep) - # POSIX allows one or two initial slashes, but treats three or more - # as single slash. - if (initial_slashes and - path.startswith(sep*2) and not path.startswith(sep*3)): - initial_slashes = 2 - comps = path.split(sep) - new_comps = [] - for comp in comps: - if comp in (empty, dot): - continue - if (comp != dotdot or (not initial_slashes and not new_comps) or - (new_comps and new_comps[-1] == dotdot)): - new_comps.append(comp) - elif new_comps: - new_comps.pop() - comps = new_comps - path = sep.join(comps) - if initial_slashes: - path = sep*initial_slashes + path - return path or dot - - -def abspath(path): - """Return an absolute path.""" - path = os.fspath(path) - if not isabs(path): - if isinstance(path, bytes): - cwd = os.getcwdb() - else: - cwd = os.getcwd() - path = join(cwd, path) - return normpath(path) - - -# Return a canonical path (i.e. the absolute location of a file on the -# filesystem). - -def realpath(filename): - """Return the canonical path of the specified filename, eliminating any -symbolic links encountered in the path.""" - filename = os.fspath(filename) - path, ok = _joinrealpath(filename[:0], filename, {}) - return abspath(path) - -# Join two paths, normalizing and eliminating any symbolic links -# encountered in the second path. -def _joinrealpath(path, rest, seen): - if isinstance(path, bytes): - sep = b'/' - curdir = b'.' - pardir = b'..' - else: - sep = '/' - curdir = '.' - pardir = '..' - - if isabs(rest): - rest = rest[1:] - path = sep - - while rest: - name, _, rest = rest.partition(sep) - if not name or name == curdir: - # current dir - continue - if name == pardir: - # parent dir - if path: - path, name = split(path) - if name == pardir: - path = join(path, pardir, pardir) - else: - path = pardir - continue - newpath = join(path, name) - if not islink(newpath): - path = newpath - continue - # Resolve the symbolic link - if newpath in seen: - # Already seen this path - path = seen[newpath] - if path is not None: - # use cached value - continue - # The symlink is not resolved, so we must have a symlink loop. - # Return already resolved part + rest of the path unchanged. - return join(newpath, rest), False - seen[newpath] = None # not resolved symlink - path, ok = _joinrealpath(path, os.readlink(newpath), seen) - if not ok: - return join(path, rest), False - seen[newpath] = path # resolved symlink - - return path, True - - -supports_unicode_filenames = (sys.platform == 'darwin') - -def relpath(path, start=None): - """Return a relative version of a path""" - - if not path: - raise ValueError("no path specified") - - path = os.fspath(path) - if isinstance(path, bytes): - curdir = b'.' - sep = b'/' - pardir = b'..' - else: - curdir = '.' - sep = '/' - pardir = '..' - - if start is None: - start = curdir - else: - start = os.fspath(start) - - try: - start_list = [x for x in abspath(start).split(sep) if x] - path_list = [x for x in abspath(path).split(sep) if x] - # Work out how much of the filepath is shared by start and path. - i = len(commonprefix([start_list, path_list])) - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return curdir - return join(*rel_list) - except (TypeError, AttributeError, BytesWarning, DeprecationWarning): - genericpath._check_arg_types('relpath', path, start) - raise - - -# Return the longest common sub-path of the sequence of paths given as input. -# The paths are not normalized before comparing them (this is the -# responsibility of the caller). Any trailing separator is stripped from the -# returned path. - -def commonpath(paths): - """Given a sequence of path names, returns the longest common sub-path.""" - - if not paths: - raise ValueError('commonpath() arg is an empty sequence') - - paths = tuple(map(os.fspath, paths)) - if isinstance(paths[0], bytes): - sep = b'/' - curdir = b'.' - else: - sep = '/' - curdir = '.' - - try: - split_paths = [path.split(sep) for path in paths] - - try: - isabs, = set(p[:1] == sep for p in paths) - except ValueError: - raise ValueError("Can't mix absolute and relative paths") from None - - split_paths = [[c for c in s if c and c != curdir] for s in split_paths] - s1 = min(split_paths) - s2 = max(split_paths) - common = s1 - for i, c in enumerate(s1): - if c != s2[i]: - common = s1[:i] - break - - prefix = sep if isabs else sep[:0] - return prefix + sep.join(common) - except (TypeError, AttributeError): - genericpath._check_arg_types('commonpath', *paths) - raise diff --git a/experiment/simulation/backend/venv/lib/python3.7/random.py b/experiment/simulation/backend/venv/lib/python3.7/random.py deleted file mode 100644 index bb6a05f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/random.py +++ /dev/null @@ -1,777 +0,0 @@ -"""Random variable generators. - - integers - -------- - uniform within range - - sequences - --------- - pick random element - pick random sample - pick weighted random sample - generate random permutation - - distributions on the real line: - ------------------------------ - uniform - triangular - normal (Gaussian) - lognormal - negative exponential - gamma - beta - pareto - Weibull - - distributions on the circle (angles 0 to 2pi) - --------------------------------------------- - circular uniform - von Mises - -General notes on the underlying Mersenne Twister core generator: - -* The period is 2**19937-1. -* It is one of the most extensively tested generators in existence. -* The random() method is implemented in C, executes in a single Python step, - and is, therefore, threadsafe. - -""" - -from warnings import warn as _warn -from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType -from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil -from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin -from os import urandom as _urandom -from _collections_abc import Set as _Set, Sequence as _Sequence -from hashlib import sha512 as _sha512 -import itertools as _itertools -import bisect as _bisect -import os as _os - -__all__ = ["Random","seed","random","uniform","randint","choice","sample", - "randrange","shuffle","normalvariate","lognormvariate", - "expovariate","vonmisesvariate","gammavariate","triangular", - "gauss","betavariate","paretovariate","weibullvariate", - "getstate","setstate", "getrandbits", "choices", - "SystemRandom"] - -NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) -TWOPI = 2.0*_pi -LOG4 = _log(4.0) -SG_MAGICCONST = 1.0 + _log(4.5) -BPF = 53 # Number of bits in a float -RECIP_BPF = 2**-BPF - - -# Translated by Guido van Rossum from C source provided by -# Adrian Baddeley. Adapted by Raymond Hettinger for use with -# the Mersenne Twister and os.urandom() core generators. - -import _random - -class Random(_random.Random): - """Random number generator base class used by bound module functions. - - Used to instantiate instances of Random to get generators that don't - share state. - - Class Random can also be subclassed if you want to use a different basic - generator of your own devising: in that case, override the following - methods: random(), seed(), getstate(), and setstate(). - Optionally, implement a getrandbits() method so that randrange() - can cover arbitrarily large ranges. - - """ - - VERSION = 3 # used by getstate/setstate - - def __init__(self, x=None): - """Initialize an instance. - - Optional argument x controls seeding, as for Random.seed(). - """ - - self.seed(x) - self.gauss_next = None - - def seed(self, a=None, version=2): - """Initialize internal state from hashable object. - - None or no argument seeds from current time or from an operating - system specific randomness source if available. - - If *a* is an int, all bits are used. - - For version 2 (the default), all of the bits are used if *a* is a str, - bytes, or bytearray. For version 1 (provided for reproducing random - sequences from older versions of Python), the algorithm for str and - bytes generates a narrower range of seeds. - - """ - - if version == 1 and isinstance(a, (str, bytes)): - a = a.decode('latin-1') if isinstance(a, bytes) else a - x = ord(a[0]) << 7 if a else 0 - for c in map(ord, a): - x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF - x ^= len(a) - a = -2 if x == -1 else x - - if version == 2 and isinstance(a, (str, bytes, bytearray)): - if isinstance(a, str): - a = a.encode() - a += _sha512(a).digest() - a = int.from_bytes(a, 'big') - - super().seed(a) - self.gauss_next = None - - def getstate(self): - """Return internal state; can be passed to setstate() later.""" - return self.VERSION, super().getstate(), self.gauss_next - - def setstate(self, state): - """Restore internal state from object returned by getstate().""" - version = state[0] - if version == 3: - version, internalstate, self.gauss_next = state - super().setstate(internalstate) - elif version == 2: - version, internalstate, self.gauss_next = state - # In version 2, the state was saved as signed ints, which causes - # inconsistencies between 32/64-bit systems. The state is - # really unsigned 32-bit ints, so we convert negative ints from - # version 2 to positive longs for version 3. - try: - internalstate = tuple(x % (2**32) for x in internalstate) - except ValueError as e: - raise TypeError from e - super().setstate(internalstate) - else: - raise ValueError("state with version %s passed to " - "Random.setstate() of version %s" % - (version, self.VERSION)) - -## ---- Methods below this point do not need to be overridden when -## ---- subclassing for the purpose of using a different core generator. - -## -------------------- pickle support ------------------- - - # Issue 17489: Since __reduce__ was defined to fix #759889 this is no - # longer called; we leave it here because it has been here since random was - # rewritten back in 2001 and why risk breaking something. - def __getstate__(self): # for pickle - return self.getstate() - - def __setstate__(self, state): # for pickle - self.setstate(state) - - def __reduce__(self): - return self.__class__, (), self.getstate() - -## -------------------- integer methods ------------------- - - def randrange(self, start, stop=None, step=1, _int=int): - """Choose a random item from range(start, stop[, step]). - - This fixes the problem with randint() which includes the - endpoint; in Python this is usually not what you want. - - """ - - # This code is a bit messy to make it fast for the - # common case while still doing adequate error checking. - istart = _int(start) - if istart != start: - raise ValueError("non-integer arg 1 for randrange()") - if stop is None: - if istart > 0: - return self._randbelow(istart) - raise ValueError("empty range for randrange()") - - # stop argument supplied. - istop = _int(stop) - if istop != stop: - raise ValueError("non-integer stop for randrange()") - width = istop - istart - if step == 1 and width > 0: - return istart + self._randbelow(width) - if step == 1: - raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width)) - - # Non-unit step argument supplied. - istep = _int(step) - if istep != step: - raise ValueError("non-integer step for randrange()") - if istep > 0: - n = (width + istep - 1) // istep - elif istep < 0: - n = (width + istep + 1) // istep - else: - raise ValueError("zero step for randrange()") - - if n <= 0: - raise ValueError("empty range for randrange()") - - return istart + istep*self._randbelow(n) - - def randint(self, a, b): - """Return random integer in range [a, b], including both end points. - """ - - return self.randrange(a, b+1) - - def _randbelow(self, n, int=int, maxsize=1<= n: - r = getrandbits(k) - return r - # There's an overridden random() method but no new getrandbits() method, - # so we can only use random() from here. - if n >= maxsize: - _warn("Underlying random() generator does not supply \n" - "enough bits to choose from a population range this large.\n" - "To remove the range limitation, add a getrandbits() method.") - return int(random() * n) - if n == 0: - raise ValueError("Boundary cannot be zero") - rem = maxsize % n - limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0 - r = random() - while r >= limit: - r = random() - return int(r*maxsize) % n - -## -------------------- sequence methods ------------------- - - def choice(self, seq): - """Choose a random element from a non-empty sequence.""" - try: - i = self._randbelow(len(seq)) - except ValueError: - raise IndexError('Cannot choose from an empty sequence') from None - return seq[i] - - def shuffle(self, x, random=None): - """Shuffle list x in place, and return None. - - Optional argument random is a 0-argument function returning a - random float in [0.0, 1.0); if it is the default None, the - standard random.random will be used. - - """ - - if random is None: - randbelow = self._randbelow - for i in reversed(range(1, len(x))): - # pick an element in x[:i+1] with which to exchange x[i] - j = randbelow(i+1) - x[i], x[j] = x[j], x[i] - else: - _int = int - for i in reversed(range(1, len(x))): - # pick an element in x[:i+1] with which to exchange x[i] - j = _int(random() * (i+1)) - x[i], x[j] = x[j], x[i] - - def sample(self, population, k): - """Chooses k unique random elements from a population sequence or set. - - Returns a new list containing elements from the population while - leaving the original population unchanged. The resulting list is - in selection order so that all sub-slices will also be valid random - samples. This allows raffle winners (the sample) to be partitioned - into grand prize and second place winners (the subslices). - - Members of the population need not be hashable or unique. If the - population contains repeats, then each occurrence is a possible - selection in the sample. - - To choose a sample in a range of integers, use range as an argument. - This is especially fast and space efficient for sampling from a - large population: sample(range(10000000), 60) - """ - - # Sampling without replacement entails tracking either potential - # selections (the pool) in a list or previous selections in a set. - - # When the number of selections is small compared to the - # population, then tracking selections is efficient, requiring - # only a small set and an occasional reselection. For - # a larger number of selections, the pool tracking method is - # preferred since the list takes less space than the - # set and it doesn't suffer from frequent reselections. - - if isinstance(population, _Set): - population = tuple(population) - if not isinstance(population, _Sequence): - raise TypeError("Population must be a sequence or set. For dicts, use list(d).") - randbelow = self._randbelow - n = len(population) - if not 0 <= k <= n: - raise ValueError("Sample larger than population or is negative") - result = [None] * k - setsize = 21 # size of a small set minus size of an empty list - if k > 5: - setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets - if n <= setsize: - # An n-length list is smaller than a k-length set - pool = list(population) - for i in range(k): # invariant: non-selected at [0,n-i) - j = randbelow(n-i) - result[i] = pool[j] - pool[j] = pool[n-i-1] # move non-selected item into vacancy - else: - selected = set() - selected_add = selected.add - for i in range(k): - j = randbelow(n) - while j in selected: - j = randbelow(n) - selected_add(j) - result[i] = population[j] - return result - - def choices(self, population, weights=None, *, cum_weights=None, k=1): - """Return a k sized list of population elements chosen with replacement. - - If the relative weights or cumulative weights are not specified, - the selections are made with equal probability. - - """ - random = self.random - if cum_weights is None: - if weights is None: - _int = int - total = len(population) - return [population[_int(random() * total)] for i in range(k)] - cum_weights = list(_itertools.accumulate(weights)) - elif weights is not None: - raise TypeError('Cannot specify both weights and cumulative weights') - if len(cum_weights) != len(population): - raise ValueError('The number of weights does not match the population') - bisect = _bisect.bisect - total = cum_weights[-1] - hi = len(cum_weights) - 1 - return [population[bisect(cum_weights, random() * total, 0, hi)] - for i in range(k)] - -## -------------------- real-valued distributions ------------------- - -## -------------------- uniform distribution ------------------- - - def uniform(self, a, b): - "Get a random number in the range [a, b) or [a, b] depending on rounding." - return a + (b-a) * self.random() - -## -------------------- triangular -------------------- - - def triangular(self, low=0.0, high=1.0, mode=None): - """Triangular distribution. - - Continuous distribution bounded by given lower and upper limits, - and having a given mode value in-between. - - http://en.wikipedia.org/wiki/Triangular_distribution - - """ - u = self.random() - try: - c = 0.5 if mode is None else (mode - low) / (high - low) - except ZeroDivisionError: - return low - if u > c: - u = 1.0 - u - c = 1.0 - c - low, high = high, low - return low + (high - low) * _sqrt(u * c) - -## -------------------- normal distribution -------------------- - - def normalvariate(self, mu, sigma): - """Normal distribution. - - mu is the mean, and sigma is the standard deviation. - - """ - # mu = mean, sigma = standard deviation - - # Uses Kinderman and Monahan method. Reference: Kinderman, - # A.J. and Monahan, J.F., "Computer generation of random - # variables using the ratio of uniform deviates", ACM Trans - # Math Software, 3, (1977), pp257-260. - - random = self.random - while 1: - u1 = random() - u2 = 1.0 - random() - z = NV_MAGICCONST*(u1-0.5)/u2 - zz = z*z/4.0 - if zz <= -_log(u2): - break - return mu + z*sigma - -## -------------------- lognormal distribution -------------------- - - def lognormvariate(self, mu, sigma): - """Log normal distribution. - - If you take the natural logarithm of this distribution, you'll get a - normal distribution with mean mu and standard deviation sigma. - mu can have any value, and sigma must be greater than zero. - - """ - return _exp(self.normalvariate(mu, sigma)) - -## -------------------- exponential distribution -------------------- - - def expovariate(self, lambd): - """Exponential distribution. - - lambd is 1.0 divided by the desired mean. It should be - nonzero. (The parameter would be called "lambda", but that is - a reserved word in Python.) Returned values range from 0 to - positive infinity if lambd is positive, and from negative - infinity to 0 if lambd is negative. - - """ - # lambd: rate lambd = 1/mean - # ('lambda' is a Python reserved word) - - # we use 1-random() instead of random() to preclude the - # possibility of taking the log of zero. - return -_log(1.0 - self.random())/lambd - -## -------------------- von Mises distribution -------------------- - - def vonmisesvariate(self, mu, kappa): - """Circular data distribution. - - mu is the mean angle, expressed in radians between 0 and 2*pi, and - kappa is the concentration parameter, which must be greater than or - equal to zero. If kappa is equal to zero, this distribution reduces - to a uniform random angle over the range 0 to 2*pi. - - """ - # mu: mean angle (in radians between 0 and 2*pi) - # kappa: concentration parameter kappa (>= 0) - # if kappa = 0 generate uniform random angle - - # Based upon an algorithm published in: Fisher, N.I., - # "Statistical Analysis of Circular Data", Cambridge - # University Press, 1993. - - # Thanks to Magnus Kessler for a correction to the - # implementation of step 4. - - random = self.random - if kappa <= 1e-6: - return TWOPI * random() - - s = 0.5 / kappa - r = s + _sqrt(1.0 + s * s) - - while 1: - u1 = random() - z = _cos(_pi * u1) - - d = z / (r + z) - u2 = random() - if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d): - break - - q = 1.0 / r - f = (q + z) / (1.0 + q * z) - u3 = random() - if u3 > 0.5: - theta = (mu + _acos(f)) % TWOPI - else: - theta = (mu - _acos(f)) % TWOPI - - return theta - -## -------------------- gamma distribution -------------------- - - def gammavariate(self, alpha, beta): - """Gamma distribution. Not the gamma function! - - Conditions on the parameters are alpha > 0 and beta > 0. - - The probability distribution function is: - - x ** (alpha - 1) * math.exp(-x / beta) - pdf(x) = -------------------------------------- - math.gamma(alpha) * beta ** alpha - - """ - - # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 - - # Warning: a few older sources define the gamma distribution in terms - # of alpha > -1.0 - if alpha <= 0.0 or beta <= 0.0: - raise ValueError('gammavariate: alpha and beta must be > 0.0') - - random = self.random - if alpha > 1.0: - - # Uses R.C.H. Cheng, "The generation of Gamma - # variables with non-integral shape parameters", - # Applied Statistics, (1977), 26, No. 1, p71-74 - - ainv = _sqrt(2.0 * alpha - 1.0) - bbb = alpha - LOG4 - ccc = alpha + ainv - - while 1: - u1 = random() - if not 1e-7 < u1 < .9999999: - continue - u2 = 1.0 - random() - v = _log(u1/(1.0-u1))/ainv - x = alpha*_exp(v) - z = u1*u1*u2 - r = bbb+ccc*v-x - if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): - return x * beta - - elif alpha == 1.0: - # expovariate(1/beta) - u = random() - while u <= 1e-7: - u = random() - return -_log(u) * beta - - else: # alpha is between 0 and 1 (exclusive) - - # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle - - while 1: - u = random() - b = (_e + alpha)/_e - p = b*u - if p <= 1.0: - x = p ** (1.0/alpha) - else: - x = -_log((b-p)/alpha) - u1 = random() - if p > 1.0: - if u1 <= x ** (alpha - 1.0): - break - elif u1 <= _exp(-x): - break - return x * beta - -## -------------------- Gauss (faster alternative) -------------------- - - def gauss(self, mu, sigma): - """Gaussian distribution. - - mu is the mean, and sigma is the standard deviation. This is - slightly faster than the normalvariate() function. - - Not thread-safe without a lock around calls. - - """ - - # When x and y are two variables from [0, 1), uniformly - # distributed, then - # - # cos(2*pi*x)*sqrt(-2*log(1-y)) - # sin(2*pi*x)*sqrt(-2*log(1-y)) - # - # are two *independent* variables with normal distribution - # (mu = 0, sigma = 1). - # (Lambert Meertens) - # (corrected version; bug discovered by Mike Miller, fixed by LM) - - # Multithreading note: When two threads call this function - # simultaneously, it is possible that they will receive the - # same return value. The window is very small though. To - # avoid this, you have to use a lock around all calls. (I - # didn't want to slow this down in the serial case by using a - # lock here.) - - random = self.random - z = self.gauss_next - self.gauss_next = None - if z is None: - x2pi = random() * TWOPI - g2rad = _sqrt(-2.0 * _log(1.0 - random())) - z = _cos(x2pi) * g2rad - self.gauss_next = _sin(x2pi) * g2rad - - return mu + z*sigma - -## -------------------- beta -------------------- -## See -## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html -## for Ivan Frohne's insightful analysis of why the original implementation: -## -## def betavariate(self, alpha, beta): -## # Discrete Event Simulation in C, pp 87-88. -## -## y = self.expovariate(alpha) -## z = self.expovariate(1.0/beta) -## return z/(y+z) -## -## was dead wrong, and how it probably got that way. - - def betavariate(self, alpha, beta): - """Beta distribution. - - Conditions on the parameters are alpha > 0 and beta > 0. - Returned values range between 0 and 1. - - """ - - # This version due to Janne Sinkkonen, and matches all the std - # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). - y = self.gammavariate(alpha, 1.0) - if y == 0: - return 0.0 - else: - return y / (y + self.gammavariate(beta, 1.0)) - -## -------------------- Pareto -------------------- - - def paretovariate(self, alpha): - """Pareto distribution. alpha is the shape parameter.""" - # Jain, pg. 495 - - u = 1.0 - self.random() - return 1.0 / u ** (1.0/alpha) - -## -------------------- Weibull -------------------- - - def weibullvariate(self, alpha, beta): - """Weibull distribution. - - alpha is the scale parameter and beta is the shape parameter. - - """ - # Jain, pg. 499; bug fix courtesy Bill Arms - - u = 1.0 - self.random() - return alpha * (-_log(u)) ** (1.0/beta) - -## --------------- Operating System Random Source ------------------ - -class SystemRandom(Random): - """Alternate random number generator using sources provided - by the operating system (such as /dev/urandom on Unix or - CryptGenRandom on Windows). - - Not available on all systems (see os.urandom() for details). - """ - - def random(self): - """Get the next random number in the range [0.0, 1.0).""" - return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF - - def getrandbits(self, k): - """getrandbits(k) -> x. Generates an int with k random bits.""" - if k <= 0: - raise ValueError('number of bits must be greater than zero') - if k != int(k): - raise TypeError('number of bits should be an integer') - numbytes = (k + 7) // 8 # bits / 8 and rounded up - x = int.from_bytes(_urandom(numbytes), 'big') - return x >> (numbytes * 8 - k) # trim excess bits - - def seed(self, *args, **kwds): - "Stub method. Not used for a system random number generator." - return None - - def _notimplemented(self, *args, **kwds): - "Method should not be called for a system random number generator." - raise NotImplementedError('System entropy source does not have state.') - getstate = setstate = _notimplemented - -## -------------------- test program -------------------- - -def _test_generator(n, func, args): - import time - print(n, 'times', func.__name__) - total = 0.0 - sqsum = 0.0 - smallest = 1e10 - largest = -1e10 - t0 = time.perf_counter() - for i in range(n): - x = func(*args) - total += x - sqsum = sqsum + x*x - smallest = min(x, smallest) - largest = max(x, largest) - t1 = time.perf_counter() - print(round(t1-t0, 3), 'sec,', end=' ') - avg = total/n - stddev = _sqrt(sqsum/n - avg*avg) - print('avg %g, stddev %g, min %g, max %g\n' % \ - (avg, stddev, smallest, largest)) - - -def _test(N=2000): - _test_generator(N, random, ()) - _test_generator(N, normalvariate, (0.0, 1.0)) - _test_generator(N, lognormvariate, (0.0, 1.0)) - _test_generator(N, vonmisesvariate, (0.0, 1.0)) - _test_generator(N, gammavariate, (0.01, 1.0)) - _test_generator(N, gammavariate, (0.1, 1.0)) - _test_generator(N, gammavariate, (0.1, 2.0)) - _test_generator(N, gammavariate, (0.5, 1.0)) - _test_generator(N, gammavariate, (0.9, 1.0)) - _test_generator(N, gammavariate, (1.0, 1.0)) - _test_generator(N, gammavariate, (2.0, 1.0)) - _test_generator(N, gammavariate, (20.0, 1.0)) - _test_generator(N, gammavariate, (200.0, 1.0)) - _test_generator(N, gauss, (0.0, 1.0)) - _test_generator(N, betavariate, (3.0, 3.0)) - _test_generator(N, triangular, (0.0, 1.0, 1.0/3.0)) - -# Create one instance, seeded from current time, and export its methods -# as module-level functions. The functions share state across all uses -#(both in the user's code and in the Python libraries), but that's fine -# for most programs and is easier for the casual user than making them -# instantiate their own Random() instance. - -_inst = Random() -seed = _inst.seed -random = _inst.random -uniform = _inst.uniform -triangular = _inst.triangular -randint = _inst.randint -choice = _inst.choice -randrange = _inst.randrange -sample = _inst.sample -shuffle = _inst.shuffle -choices = _inst.choices -normalvariate = _inst.normalvariate -lognormvariate = _inst.lognormvariate -expovariate = _inst.expovariate -vonmisesvariate = _inst.vonmisesvariate -gammavariate = _inst.gammavariate -gauss = _inst.gauss -betavariate = _inst.betavariate -paretovariate = _inst.paretovariate -weibullvariate = _inst.weibullvariate -getstate = _inst.getstate -setstate = _inst.setstate -getrandbits = _inst.getrandbits - -if hasattr(_os, "fork"): - _os.register_at_fork(after_in_child=_inst.seed) - - -if __name__ == '__main__': - _test() diff --git a/experiment/simulation/backend/venv/lib/python3.7/re.py b/experiment/simulation/backend/venv/lib/python3.7/re.py deleted file mode 100644 index 94d4865..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/re.py +++ /dev/null @@ -1,366 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# re-compatible interface for the sre matching engine -# -# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. -# -# This version of the SRE library can be redistributed under CNRI's -# Python 1.6 license. For any other use, please contact Secret Labs -# AB (info@pythonware.com). -# -# Portions of this engine have been developed in cooperation with -# CNRI. Hewlett-Packard provided funding for 1.6 integration and -# other compatibility work. -# - -r"""Support for regular expressions (RE). - -This module provides regular expression matching operations similar to -those found in Perl. It supports both 8-bit and Unicode strings; both -the pattern and the strings being processed can contain null bytes and -characters outside the US ASCII range. - -Regular expressions can contain both special and ordinary characters. -Most ordinary characters, like "A", "a", or "0", are the simplest -regular expressions; they simply match themselves. You can -concatenate ordinary characters, so last matches the string 'last'. - -The special characters are: - "." Matches any character except a newline. - "^" Matches the start of the string. - "$" Matches the end of the string or just before the newline at - the end of the string. - "*" Matches 0 or more (greedy) repetitions of the preceding RE. - Greedy means that it will match as many repetitions as possible. - "+" Matches 1 or more (greedy) repetitions of the preceding RE. - "?" Matches 0 or 1 (greedy) of the preceding RE. - *?,+?,?? Non-greedy versions of the previous three special characters. - {m,n} Matches from m to n repetitions of the preceding RE. - {m,n}? Non-greedy version of the above. - "\\" Either escapes special characters or signals a special sequence. - [] Indicates a set of characters. - A "^" as the first character indicates a complementing set. - "|" A|B, creates an RE that will match either A or B. - (...) Matches the RE inside the parentheses. - The contents can be retrieved or matched later in the string. - (?aiLmsux) Set the A, I, L, M, S, U, or X flag for the RE (see below). - (?:...) Non-grouping version of regular parentheses. - (?P...) The substring matched by the group is accessible by name. - (?P=name) Matches the text matched earlier by the group named name. - (?#...) A comment; ignored. - (?=...) Matches if ... matches next, but doesn't consume the string. - (?!...) Matches if ... doesn't match next. - (?<=...) Matches if preceded by ... (must be fixed length). - (?= _MAXCACHE: - # Drop the oldest item - try: - del _cache[next(iter(_cache))] - except (StopIteration, RuntimeError, KeyError): - pass - _cache[type(pattern), pattern, flags] = p - return p - -@functools.lru_cache(_MAXCACHE) -def _compile_repl(repl, pattern): - # internal: compile replacement pattern - return sre_parse.parse_template(repl, pattern) - -def _expand(pattern, match, template): - # internal: Match.expand implementation hook - template = sre_parse.parse_template(template, pattern) - return sre_parse.expand_template(template, match) - -def _subx(pattern, template): - # internal: Pattern.sub/subn implementation helper - template = _compile_repl(template, pattern) - if not template[0] and len(template[1]) == 1: - # literal replacement - return template[1][0] - def filter(match, template=template): - return sre_parse.expand_template(template, match) - return filter - -# register myself for pickling - -import copyreg - -def _pickle(p): - return _compile, (p.pattern, p.flags) - -copyreg.pickle(Pattern, _pickle, _compile) - -# -------------------------------------------------------------------- -# experimental stuff (see python-dev discussions for details) - -class Scanner: - def __init__(self, lexicon, flags=0): - from sre_constants import BRANCH, SUBPATTERN - if isinstance(flags, RegexFlag): - flags = flags.value - self.lexicon = lexicon - # combine phrases into a compound pattern - p = [] - s = sre_parse.Pattern() - s.flags = flags - for phrase, action in lexicon: - gid = s.opengroup() - p.append(sre_parse.SubPattern(s, [ - (SUBPATTERN, (gid, 0, 0, sre_parse.parse(phrase, flags))), - ])) - s.closegroup(gid, p[-1]) - p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) - self.scanner = sre_compile.compile(p) - def scan(self, string): - result = [] - append = result.append - match = self.scanner.scanner(string).match - i = 0 - while True: - m = match() - if not m: - break - j = m.end() - if i == j: - break - action = self.lexicon[m.lastindex-1][1] - if callable(action): - self.match = m - action = action(self, m.group()) - if action is not None: - append(action) - i = j - return result, string[i:] diff --git a/experiment/simulation/backend/venv/lib/python3.7/reprlib.py b/experiment/simulation/backend/venv/lib/python3.7/reprlib.py deleted file mode 100644 index 616b343..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/reprlib.py +++ /dev/null @@ -1,161 +0,0 @@ -"""Redo the builtin repr() (representation) but with limits on most sizes.""" - -__all__ = ["Repr", "repr", "recursive_repr"] - -import builtins -from itertools import islice -from _thread import get_ident - -def recursive_repr(fillvalue='...'): - 'Decorator to make a repr function return fillvalue for a recursive call' - - def decorating_function(user_function): - repr_running = set() - - def wrapper(self): - key = id(self), get_ident() - if key in repr_running: - return fillvalue - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - - # Can't use functools.wraps() here because of bootstrap issues - wrapper.__module__ = getattr(user_function, '__module__') - wrapper.__doc__ = getattr(user_function, '__doc__') - wrapper.__name__ = getattr(user_function, '__name__') - wrapper.__qualname__ = getattr(user_function, '__qualname__') - wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) - return wrapper - - return decorating_function - -class Repr: - - def __init__(self): - self.maxlevel = 6 - self.maxtuple = 6 - self.maxlist = 6 - self.maxarray = 5 - self.maxdict = 4 - self.maxset = 6 - self.maxfrozenset = 6 - self.maxdeque = 6 - self.maxstring = 30 - self.maxlong = 40 - self.maxother = 30 - - def repr(self, x): - return self.repr1(x, self.maxlevel) - - def repr1(self, x, level): - typename = type(x).__name__ - if ' ' in typename: - parts = typename.split() - typename = '_'.join(parts) - if hasattr(self, 'repr_' + typename): - return getattr(self, 'repr_' + typename)(x, level) - else: - return self.repr_instance(x, level) - - def _repr_iterable(self, x, level, left, right, maxiter, trail=''): - n = len(x) - if level <= 0 and n: - s = '...' - else: - newlevel = level - 1 - repr1 = self.repr1 - pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)] - if n > maxiter: pieces.append('...') - s = ', '.join(pieces) - if n == 1 and trail: right = trail + right - return '%s%s%s' % (left, s, right) - - def repr_tuple(self, x, level): - return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',') - - def repr_list(self, x, level): - return self._repr_iterable(x, level, '[', ']', self.maxlist) - - def repr_array(self, x, level): - if not x: - return "array('%s')" % x.typecode - header = "array('%s', [" % x.typecode - return self._repr_iterable(x, level, header, '])', self.maxarray) - - def repr_set(self, x, level): - if not x: - return 'set()' - x = _possibly_sorted(x) - return self._repr_iterable(x, level, '{', '}', self.maxset) - - def repr_frozenset(self, x, level): - if not x: - return 'frozenset()' - x = _possibly_sorted(x) - return self._repr_iterable(x, level, 'frozenset({', '})', - self.maxfrozenset) - - def repr_deque(self, x, level): - return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque) - - def repr_dict(self, x, level): - n = len(x) - if n == 0: return '{}' - if level <= 0: return '{...}' - newlevel = level - 1 - repr1 = self.repr1 - pieces = [] - for key in islice(_possibly_sorted(x), self.maxdict): - keyrepr = repr1(key, newlevel) - valrepr = repr1(x[key], newlevel) - pieces.append('%s: %s' % (keyrepr, valrepr)) - if n > self.maxdict: pieces.append('...') - s = ', '.join(pieces) - return '{%s}' % (s,) - - def repr_str(self, x, level): - s = builtins.repr(x[:self.maxstring]) - if len(s) > self.maxstring: - i = max(0, (self.maxstring-3)//2) - j = max(0, self.maxstring-3-i) - s = builtins.repr(x[:i] + x[len(x)-j:]) - s = s[:i] + '...' + s[len(s)-j:] - return s - - def repr_int(self, x, level): - s = builtins.repr(x) # XXX Hope this isn't too slow... - if len(s) > self.maxlong: - i = max(0, (self.maxlong-3)//2) - j = max(0, self.maxlong-3-i) - s = s[:i] + '...' + s[len(s)-j:] - return s - - def repr_instance(self, x, level): - try: - s = builtins.repr(x) - # Bugs in x.__repr__() can cause arbitrary - # exceptions -- then make up something - except Exception: - return '<%s instance at %#x>' % (x.__class__.__name__, id(x)) - if len(s) > self.maxother: - i = max(0, (self.maxother-3)//2) - j = max(0, self.maxother-3-i) - s = s[:i] + '...' + s[len(s)-j:] - return s - - -def _possibly_sorted(x): - # Since not all sequences of items can be sorted and comparison - # functions may raise arbitrary exceptions, return an unsorted - # sequence in that case. - try: - return sorted(x) - except Exception: - return list(x) - -aRepr = Repr() -repr = aRepr.repr diff --git a/experiment/simulation/backend/venv/lib/python3.7/rlcompleter.py b/experiment/simulation/backend/venv/lib/python3.7/rlcompleter.py deleted file mode 100644 index bca4a7b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/rlcompleter.py +++ /dev/null @@ -1,205 +0,0 @@ -"""Word completion for GNU readline. - -The completer completes keywords, built-ins and globals in a selectable -namespace (which defaults to __main__); when completing NAME.NAME..., it -evaluates (!) the expression up to the last dot and completes its attributes. - -It's very cool to do "import sys" type "sys.", hit the completion key (twice), -and see the list of names defined by the sys module! - -Tip: to use the tab key as the completion key, call - - readline.parse_and_bind("tab: complete") - -Notes: - -- Exceptions raised by the completer function are *ignored* (and generally cause - the completion to fail). This is a feature -- since readline sets the tty - device in raw (or cbreak) mode, printing a traceback wouldn't work well - without some complicated hoopla to save, reset and restore the tty state. - -- The evaluation of the NAME.NAME... form may cause arbitrary application - defined code to be executed if an object with a __getattr__ hook is found. - Since it is the responsibility of the application (or the user) to enable this - feature, I consider this an acceptable risk. More complicated expressions - (e.g. function calls or indexing operations) are *not* evaluated. - -- When the original stdin is not a tty device, GNU readline is never - used, and this module (and the readline module) are silently inactive. - -""" - -import atexit -import builtins -import __main__ - -__all__ = ["Completer"] - -class Completer: - def __init__(self, namespace = None): - """Create a new completer for the command line. - - Completer([namespace]) -> completer instance. - - If unspecified, the default namespace where completions are performed - is __main__ (technically, __main__.__dict__). Namespaces should be - given as dictionaries. - - Completer instances should be used as the completion mechanism of - readline via the set_completer() call: - - readline.set_completer(Completer(my_namespace).complete) - """ - - if namespace and not isinstance(namespace, dict): - raise TypeError('namespace must be a dictionary') - - # Don't bind to namespace quite yet, but flag whether the user wants a - # specific namespace or to use __main__.__dict__. This will allow us - # to bind to __main__.__dict__ at completion time, not now. - if namespace is None: - self.use_main_ns = 1 - else: - self.use_main_ns = 0 - self.namespace = namespace - - def complete(self, text, state): - """Return the next possible completion for 'text'. - - This is called successively with state == 0, 1, 2, ... until it - returns None. The completion should begin with 'text'. - - """ - if self.use_main_ns: - self.namespace = __main__.__dict__ - - if not text.strip(): - if state == 0: - if _readline_available: - readline.insert_text('\t') - readline.redisplay() - return '' - else: - return '\t' - else: - return None - - if state == 0: - if "." in text: - self.matches = self.attr_matches(text) - else: - self.matches = self.global_matches(text) - try: - return self.matches[state] - except IndexError: - return None - - def _callable_postfix(self, val, word): - if callable(val): - word = word + "(" - return word - - def global_matches(self, text): - """Compute matches when text is a simple name. - - Return a list of all keywords, built-in functions and names currently - defined in self.namespace that match. - - """ - import keyword - matches = [] - seen = {"__builtins__"} - n = len(text) - for word in keyword.kwlist: - if word[:n] == text: - seen.add(word) - if word in {'finally', 'try'}: - word = word + ':' - elif word not in {'False', 'None', 'True', - 'break', 'continue', 'pass', - 'else'}: - word = word + ' ' - matches.append(word) - for nspace in [self.namespace, builtins.__dict__]: - for word, val in nspace.items(): - if word[:n] == text and word not in seen: - seen.add(word) - matches.append(self._callable_postfix(val, word)) - return matches - - def attr_matches(self, text): - """Compute matches when text contains a dot. - - Assuming the text is of the form NAME.NAME....[NAME], and is - evaluable in self.namespace, it will be evaluated and its attributes - (as revealed by dir()) are used as possible completions. (For class - instances, class members are also considered.) - - WARNING: this can still invoke arbitrary C code, if an object - with a __getattr__ hook is evaluated. - - """ - import re - m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) - if not m: - return [] - expr, attr = m.group(1, 3) - try: - thisobject = eval(expr, self.namespace) - except Exception: - return [] - - # get the content of the object, except __builtins__ - words = set(dir(thisobject)) - words.discard("__builtins__") - - if hasattr(thisobject, '__class__'): - words.add('__class__') - words.update(get_class_members(thisobject.__class__)) - matches = [] - n = len(attr) - if attr == '': - noprefix = '_' - elif attr == '_': - noprefix = '__' - else: - noprefix = None - while True: - for word in words: - if (word[:n] == attr and - not (noprefix and word[:n+1] == noprefix)): - match = "%s.%s" % (expr, word) - try: - val = getattr(thisobject, word) - except Exception: - pass # Include even if attribute not set - else: - match = self._callable_postfix(val, match) - matches.append(match) - if matches or not noprefix: - break - if noprefix == '_': - noprefix = '__' - else: - noprefix = None - matches.sort() - return matches - -def get_class_members(klass): - ret = dir(klass) - if hasattr(klass,'__bases__'): - for base in klass.__bases__: - ret = ret + get_class_members(base) - return ret - -try: - import readline -except ImportError: - _readline_available = False -else: - readline.set_completer(Completer().complete) - # Release references early at shutdown (the readline module's - # contents are quasi-immortal, and the completer function holds a - # reference to globals). - atexit.register(lambda: readline.set_completer(None)) - _readline_available = True diff --git a/experiment/simulation/backend/venv/lib/python3.7/shutil.py b/experiment/simulation/backend/venv/lib/python3.7/shutil.py deleted file mode 100644 index fc6fb4e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/shutil.py +++ /dev/null @@ -1,1188 +0,0 @@ -"""Utility functions for copying and archiving files and directory trees. - -XXX The functions here don't copy the resource fork or other metadata on Mac. - -""" - -import os -import sys -import stat -import fnmatch -import collections -import errno - -try: - import zlib - del zlib - _ZLIB_SUPPORTED = True -except ImportError: - _ZLIB_SUPPORTED = False - -try: - import bz2 - del bz2 - _BZ2_SUPPORTED = True -except ImportError: - _BZ2_SUPPORTED = False - -try: - import lzma - del lzma - _LZMA_SUPPORTED = True -except ImportError: - _LZMA_SUPPORTED = False - -try: - from pwd import getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam -except ImportError: - getgrnam = None - -__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", - "copytree", "move", "rmtree", "Error", "SpecialFileError", - "ExecError", "make_archive", "get_archive_formats", - "register_archive_format", "unregister_archive_format", - "get_unpack_formats", "register_unpack_format", - "unregister_unpack_format", "unpack_archive", - "ignore_patterns", "chown", "which", "get_terminal_size", - "SameFileError"] - # disk_usage is added later, if available on the platform - -class Error(OSError): - pass - -class SameFileError(Error): - """Raised when source and destination are the same file.""" - -class SpecialFileError(OSError): - """Raised when trying to do a kind of operation (e.g. copying) which is - not supported on a special file (e.g. a named pipe)""" - -class ExecError(OSError): - """Raised when a command could not be executed""" - -class ReadError(OSError): - """Raised when an archive cannot be read""" - -class RegistryError(Exception): - """Raised when a registry operation with the archiving - and unpacking registries fails""" - - -def copyfileobj(fsrc, fdst, length=16*1024): - """copy data from file-like object fsrc to file-like object fdst""" - while 1: - buf = fsrc.read(length) - if not buf: - break - fdst.write(buf) - -def _samefile(src, dst): - # Macintosh, Unix. - if hasattr(os.path, 'samefile'): - try: - return os.path.samefile(src, dst) - except OSError: - return False - - # All other platforms: check for same pathname. - return (os.path.normcase(os.path.abspath(src)) == - os.path.normcase(os.path.abspath(dst))) - -def copyfile(src, dst, *, follow_symlinks=True): - """Copy data from src to dst. - - If follow_symlinks is not set and src is a symbolic link, a new - symlink will be created instead of copying the file it points to. - - """ - if _samefile(src, dst): - raise SameFileError("{!r} and {!r} are the same file".format(src, dst)) - - for fn in [src, dst]: - try: - st = os.stat(fn) - except OSError: - # File most likely does not exist - pass - else: - # XXX What about other special files? (sockets, devices...) - if stat.S_ISFIFO(st.st_mode): - raise SpecialFileError("`%s` is a named pipe" % fn) - - if not follow_symlinks and os.path.islink(src): - os.symlink(os.readlink(src), dst) - else: - with open(src, 'rb') as fsrc: - with open(dst, 'wb') as fdst: - copyfileobj(fsrc, fdst) - return dst - -def copymode(src, dst, *, follow_symlinks=True): - """Copy mode bits from src to dst. - - If follow_symlinks is not set, symlinks aren't followed if and only - if both `src` and `dst` are symlinks. If `lchmod` isn't available - (e.g. Linux) this method does nothing. - - """ - if not follow_symlinks and os.path.islink(src) and os.path.islink(dst): - if hasattr(os, 'lchmod'): - stat_func, chmod_func = os.lstat, os.lchmod - else: - return - elif hasattr(os, 'chmod'): - stat_func, chmod_func = os.stat, os.chmod - else: - return - - st = stat_func(src) - chmod_func(dst, stat.S_IMODE(st.st_mode)) - -if hasattr(os, 'listxattr'): - def _copyxattr(src, dst, *, follow_symlinks=True): - """Copy extended filesystem attributes from `src` to `dst`. - - Overwrite existing attributes. - - If `follow_symlinks` is false, symlinks won't be followed. - - """ - - try: - names = os.listxattr(src, follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL): - raise - return - for name in names: - try: - value = os.getxattr(src, name, follow_symlinks=follow_symlinks) - os.setxattr(dst, name, value, follow_symlinks=follow_symlinks) - except OSError as e: - if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA, - errno.EINVAL): - raise -else: - def _copyxattr(*args, **kwargs): - pass - -def copystat(src, dst, *, follow_symlinks=True): - """Copy file metadata - - Copy the permission bits, last access time, last modification time, and - flags from `src` to `dst`. On Linux, copystat() also copies the "extended - attributes" where possible. The file contents, owner, and group are - unaffected. `src` and `dst` are path names given as strings. - - If the optional flag `follow_symlinks` is not set, symlinks aren't - followed if and only if both `src` and `dst` are symlinks. - """ - def _nop(*args, ns=None, follow_symlinks=None): - pass - - # follow symlinks (aka don't not follow symlinks) - follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst)) - if follow: - # use the real function if it exists - def lookup(name): - return getattr(os, name, _nop) - else: - # use the real function only if it exists - # *and* it supports follow_symlinks - def lookup(name): - fn = getattr(os, name, _nop) - if fn in os.supports_follow_symlinks: - return fn - return _nop - - st = lookup("stat")(src, follow_symlinks=follow) - mode = stat.S_IMODE(st.st_mode) - lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns), - follow_symlinks=follow) - # We must copy extended attributes before the file is (potentially) - # chmod()'ed read-only, otherwise setxattr() will error with -EACCES. - _copyxattr(src, dst, follow_symlinks=follow) - try: - lookup("chmod")(dst, mode, follow_symlinks=follow) - except NotImplementedError: - # if we got a NotImplementedError, it's because - # * follow_symlinks=False, - # * lchown() is unavailable, and - # * either - # * fchownat() is unavailable or - # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW. - # (it returned ENOSUP.) - # therefore we're out of options--we simply cannot chown the - # symlink. give up, suppress the error. - # (which is what shutil always did in this circumstance.) - pass - if hasattr(st, 'st_flags'): - try: - lookup("chflags")(dst, st.st_flags, follow_symlinks=follow) - except OSError as why: - for err in 'EOPNOTSUPP', 'ENOTSUP': - if hasattr(errno, err) and why.errno == getattr(errno, err): - break - else: - raise - -def copy(src, dst, *, follow_symlinks=True): - """Copy data and mode bits ("cp src dst"). Return the file's destination. - - The destination may be a directory. - - If follow_symlinks is false, symlinks won't be followed. This - resembles GNU's "cp -P src dst". - - If source and destination are the same file, a SameFileError will be - raised. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst, follow_symlinks=follow_symlinks) - copymode(src, dst, follow_symlinks=follow_symlinks) - return dst - -def copy2(src, dst, *, follow_symlinks=True): - """Copy data and metadata. Return the file's destination. - - Metadata is copied with copystat(). Please see the copystat function - for more information. - - The destination may be a directory. - - If follow_symlinks is false, symlinks won't be followed. This - resembles GNU's "cp -P src dst". - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst, follow_symlinks=follow_symlinks) - copystat(src, dst, follow_symlinks=follow_symlinks) - return dst - -def ignore_patterns(*patterns): - """Function that can be used as copytree() ignore parameter. - - Patterns is a sequence of glob-style patterns - that are used to exclude files""" - def _ignore_patterns(path, names): - ignored_names = [] - for pattern in patterns: - ignored_names.extend(fnmatch.filter(names, pattern)) - return set(ignored_names) - return _ignore_patterns - -def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False): - """Recursively copy a directory tree. - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. If the file pointed by the symlink doesn't - exist, an exception will be added in the list of errors raised in - an Error exception at the end of the copy process. - - You can set the optional ignore_dangling_symlinks flag to true if you - want to silence this exception. Notice that this has no effect on - platforms that don't support os.symlink. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - The optional copy_function argument is a callable that will be used - to copy each file. It will be called with the source path and the - destination path as arguments. By default, copy2() is used, but any - function that supports the same signature (like copy()) can be used. - - """ - names = os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - os.makedirs(dst) - errors = [] - for name in names: - if name in ignored_names: - continue - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.islink(srcname): - linkto = os.readlink(srcname) - if symlinks: - # We can't just leave it to `copy_function` because legacy - # code with a custom `copy_function` may rely on copytree - # doing the right thing. - os.symlink(linkto, dstname) - copystat(srcname, dstname, follow_symlinks=not symlinks) - else: - # ignore dangling symlink if the flag is on - if not os.path.exists(linkto) and ignore_dangling_symlinks: - continue - # otherwise let the copy occurs. copy2 will raise an error - if os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, - copy_function) - else: - copy_function(srcname, dstname) - elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, copy_function) - else: - # Will raise a SpecialFileError for unsupported file types - copy_function(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except Error as err: - errors.extend(err.args[0]) - except OSError as why: - errors.append((srcname, dstname, str(why))) - try: - copystat(src, dst) - except OSError as why: - # Copying file access times may fail on Windows - if getattr(why, 'winerror', None) is None: - errors.append((src, dst, str(why))) - if errors: - raise Error(errors) - return dst - -# version vulnerable to race conditions -def _rmtree_unsafe(path, onerror): - try: - with os.scandir(path) as scandir_it: - entries = list(scandir_it) - except OSError: - onerror(os.scandir, path, sys.exc_info()) - entries = [] - for entry in entries: - fullname = entry.path - try: - is_dir = entry.is_dir(follow_symlinks=False) - except OSError: - is_dir = False - if is_dir: - try: - if entry.is_symlink(): - # This can only happen if someone replaces - # a directory with a symlink after the call to - # os.scandir or entry.is_dir above. - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, fullname, sys.exc_info()) - continue - _rmtree_unsafe(fullname, onerror) - else: - try: - os.unlink(fullname) - except OSError: - onerror(os.unlink, fullname, sys.exc_info()) - try: - os.rmdir(path) - except OSError: - onerror(os.rmdir, path, sys.exc_info()) - -# Version using fd-based APIs to protect against races -def _rmtree_safe_fd(topfd, path, onerror): - try: - with os.scandir(topfd) as scandir_it: - entries = list(scandir_it) - except OSError as err: - err.filename = path - onerror(os.scandir, path, sys.exc_info()) - return - for entry in entries: - fullname = os.path.join(path, entry.name) - try: - is_dir = entry.is_dir(follow_symlinks=False) - if is_dir: - orig_st = entry.stat(follow_symlinks=False) - is_dir = stat.S_ISDIR(orig_st.st_mode) - except OSError: - is_dir = False - if is_dir: - try: - dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd) - except OSError: - onerror(os.open, fullname, sys.exc_info()) - else: - try: - if os.path.samestat(orig_st, os.fstat(dirfd)): - _rmtree_safe_fd(dirfd, fullname, onerror) - try: - os.rmdir(entry.name, dir_fd=topfd) - except OSError: - onerror(os.rmdir, fullname, sys.exc_info()) - else: - try: - # This can only happen if someone replaces - # a directory with a symlink after the call to - # os.scandir or stat.S_ISDIR above. - raise OSError("Cannot call rmtree on a symbolic " - "link") - except OSError: - onerror(os.path.islink, fullname, sys.exc_info()) - finally: - os.close(dirfd) - else: - try: - os.unlink(entry.name, dir_fd=topfd) - except OSError: - onerror(os.unlink, fullname, sys.exc_info()) - -_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <= - os.supports_dir_fd and - os.scandir in os.supports_fd and - os.stat in os.supports_follow_symlinks) - -def rmtree(path, ignore_errors=False, onerror=None): - """Recursively delete a directory tree. - - If ignore_errors is set, errors are ignored; otherwise, if onerror - is set, it is called to handle the error with arguments (func, - path, exc_info) where func is platform and implementation dependent; - path is the argument to that function that caused it to fail; and - exc_info is a tuple returned by sys.exc_info(). If ignore_errors - is false and onerror is None, an exception is raised. - - """ - if ignore_errors: - def onerror(*args): - pass - elif onerror is None: - def onerror(*args): - raise - if _use_fd_functions: - # While the unsafe rmtree works fine on bytes, the fd based does not. - if isinstance(path, bytes): - path = os.fsdecode(path) - # Note: To guard against symlink races, we use the standard - # lstat()/open()/fstat() trick. - try: - orig_st = os.lstat(path) - except Exception: - onerror(os.lstat, path, sys.exc_info()) - return - try: - fd = os.open(path, os.O_RDONLY) - except Exception: - onerror(os.lstat, path, sys.exc_info()) - return - try: - if os.path.samestat(orig_st, os.fstat(fd)): - _rmtree_safe_fd(fd, path, onerror) - try: - os.rmdir(path) - except OSError: - onerror(os.rmdir, path, sys.exc_info()) - else: - try: - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - finally: - os.close(fd) - else: - try: - if os.path.islink(path): - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - # can't continue even if onerror hook returns - return - return _rmtree_unsafe(path, onerror) - -# Allow introspection of whether or not the hardening against symlink -# attacks is supported on the current platform -rmtree.avoids_symlink_attacks = _use_fd_functions - -def _basename(path): - # A basename() variant which first strips the trailing slash, if present. - # Thus we always get the last component of the path, even for directories. - sep = os.path.sep + (os.path.altsep or '') - return os.path.basename(path.rstrip(sep)) - -def move(src, dst, copy_function=copy2): - """Recursively move a file or directory to another location. This is - similar to the Unix "mv" command. Return the file or directory's - destination. - - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. - - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. - - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. Symlinks are - recreated under the new name if os.rename() fails because of cross - filesystem renames. - - The optional `copy_function` argument is a callable that will be used - to copy the source or it will be delegated to `copytree`. - By default, copy2() is used, but any function that supports the same - signature (like copy()) can be used. - - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - real_dst = dst - if os.path.isdir(dst): - if _samefile(src, dst): - # We might be on a case insensitive filesystem, - # perform the rename anyway. - os.rename(src, dst) - return - - real_dst = os.path.join(dst, _basename(src)) - if os.path.exists(real_dst): - raise Error("Destination path '%s' already exists" % real_dst) - try: - os.rename(src, real_dst) - except OSError: - if os.path.islink(src): - linkto = os.readlink(src) - os.symlink(linkto, real_dst) - os.unlink(src) - elif os.path.isdir(src): - if _destinsrc(src, dst): - raise Error("Cannot move a directory '%s' into itself" - " '%s'." % (src, dst)) - copytree(src, real_dst, copy_function=copy_function, - symlinks=True) - rmtree(src) - else: - copy_function(src, real_dst) - os.unlink(src) - return real_dst - -def _destinsrc(src, dst): - src = os.path.abspath(src) - dst = os.path.abspath(dst) - if not src.endswith(os.path.sep): - src += os.path.sep - if not dst.endswith(os.path.sep): - dst += os.path.sep - return dst.startswith(src) - -def _get_gid(name): - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _get_uid(name): - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, - owner=None, group=None, logger=None): - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", "xz", or None. - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", ".bz2", or ".xz"). - - Returns the output filename. - """ - if compress is None: - tar_compression = '' - elif _ZLIB_SUPPORTED and compress == 'gzip': - tar_compression = 'gz' - elif _BZ2_SUPPORTED and compress == 'bzip2': - tar_compression = 'bz2' - elif _LZMA_SUPPORTED and compress == 'xz': - tar_compression = 'xz' - else: - raise ValueError("bad value for 'compress', or compression format not " - "supported : {0}".format(compress)) - - import tarfile # late import for breaking circular dependency - - compress_ext = '.' + tar_compression if compress else '' - archive_name = base_name + '.tar' + compress_ext - archive_dir = os.path.dirname(archive_name) - - if archive_dir and not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # creating the tarball - if logger is not None: - logger.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - return archive_name - -def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Returns the - name of the output zip file. - """ - import zipfile # late import for breaking circular dependency - - zip_filename = base_name + ".zip" - archive_dir = os.path.dirname(base_name) - - if archive_dir and not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - if logger is not None: - logger.info("creating '%s' and adding '%s' to it", - zip_filename, base_dir) - - if not dry_run: - with zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) as zf: - path = os.path.normpath(base_dir) - if path != os.curdir: - zf.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in sorted(dirnames): - path = os.path.normpath(os.path.join(dirpath, name)) - zf.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zf.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - - return zip_filename - -_ARCHIVE_FORMATS = { - 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), -} - -if _ZLIB_SUPPORTED: - _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')], - "gzip'ed tar-file") - _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file") - -if _BZ2_SUPPORTED: - _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], - "bzip2'ed tar-file") - -if _LZMA_SUPPORTED: - _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')], - "xz'ed tar-file") - -def get_archive_formats(): - """Returns a list of supported formats for archiving and unarchiving. - - Each element of the returned sequence is a tuple (name, description) - """ - formats = [(name, registry[2]) for name, registry in - _ARCHIVE_FORMATS.items()] - formats.sort() - return formats - -def register_archive_format(name, function, extra_args=None, description=''): - """Registers an archive format. - - name is the name of the format. function is the callable that will be - used to create archives. If provided, extra_args is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_archive_formats() function. - """ - if extra_args is None: - extra_args = [] - if not callable(function): - raise TypeError('The %s object is not callable' % function) - if not isinstance(extra_args, (tuple, list)): - raise TypeError('extra_args needs to be a sequence') - for element in extra_args: - if not isinstance(element, (tuple, list)) or len(element) !=2: - raise TypeError('extra_args elements are : (arg_name, value)') - - _ARCHIVE_FORMATS[name] = (function, extra_args, description) - -def unregister_archive_format(name): - del _ARCHIVE_FORMATS[name] - -def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, - dry_run=0, owner=None, group=None, logger=None): - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "gztar", - "bztar", or "xztar". Or any other registered format. - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - if logger is not None: - logger.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run, 'logger': logger} - - try: - format_info = _ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) from None - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - if logger is not None: - logger.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename - - -def get_unpack_formats(): - """Returns a list of supported formats for unpacking. - - Each element of the returned sequence is a tuple - (name, extensions, description) - """ - formats = [(name, info[0], info[3]) for name, info in - _UNPACK_FORMATS.items()] - formats.sort() - return formats - -def _check_unpack_options(extensions, function, extra_args): - """Checks what gets registered as an unpacker.""" - # first make sure no other unpacker is registered for this extension - existing_extensions = {} - for name, info in _UNPACK_FORMATS.items(): - for ext in info[0]: - existing_extensions[ext] = name - - for extension in extensions: - if extension in existing_extensions: - msg = '%s is already registered for "%s"' - raise RegistryError(msg % (extension, - existing_extensions[extension])) - - if not callable(function): - raise TypeError('The registered function must be a callable') - - -def register_unpack_format(name, extensions, function, extra_args=None, - description=''): - """Registers an unpack format. - - `name` is the name of the format. `extensions` is a list of extensions - corresponding to the format. - - `function` is the callable that will be - used to unpack archives. The callable will receive archives to unpack. - If it's unable to handle an archive, it needs to raise a ReadError - exception. - - If provided, `extra_args` is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_unpack_formats() function. - """ - if extra_args is None: - extra_args = [] - _check_unpack_options(extensions, function, extra_args) - _UNPACK_FORMATS[name] = extensions, function, extra_args, description - -def unregister_unpack_format(name): - """Removes the pack format from the registry.""" - del _UNPACK_FORMATS[name] - -def _ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - -def _unpack_zipfile(filename, extract_dir): - """Unpack zip `filename` to `extract_dir` - """ - import zipfile # late import for breaking circular dependency - - if not zipfile.is_zipfile(filename): - raise ReadError("%s is not a zip file" % filename) - - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - target = os.path.join(extract_dir, *name.split('/')) - if not target: - continue - - _ensure_directory(target) - if not name.endswith('/'): - # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data - finally: - zip.close() - -def _unpack_tarfile(filename, extract_dir): - """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir` - """ - import tarfile # late import for breaking circular dependency - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise ReadError( - "%s is not a compressed or uncompressed tar file" % filename) - try: - tarobj.extractall(extract_dir) - finally: - tarobj.close() - -_UNPACK_FORMATS = { - 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), - 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"), -} - -if _ZLIB_SUPPORTED: - _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [], - "gzip'ed tar-file") - -if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [], - "bzip2'ed tar-file") - -if _LZMA_SUPPORTED: - _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [], - "xz'ed tar-file") - -def _find_unpack_format(filename): - for name, info in _UNPACK_FORMATS.items(): - for extension in info[0]: - if filename.endswith(extension): - return name - return None - -def unpack_archive(filename, extract_dir=None, format=None): - """Unpack an archive. - - `filename` is the name of the archive. - - `extract_dir` is the name of the target directory, where the archive - is unpacked. If not provided, the current working directory is used. - - `format` is the archive format: one of "zip", "tar", "gztar", "bztar", - or "xztar". Or any other registered format. If not provided, - unpack_archive will use the filename extension and see if an unpacker - was registered for that extension. - - In case none is found, a ValueError is raised. - """ - if extract_dir is None: - extract_dir = os.getcwd() - - extract_dir = os.fspath(extract_dir) - filename = os.fspath(filename) - - if format is not None: - try: - format_info = _UNPACK_FORMATS[format] - except KeyError: - raise ValueError("Unknown unpack format '{0}'".format(format)) from None - - func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) - else: - # we need to look at the registered unpackers supported extensions - format = _find_unpack_format(filename) - if format is None: - raise ReadError("Unknown archive format '{0}'".format(filename)) - - func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) - func(filename, extract_dir, **kwargs) - - -if hasattr(os, 'statvfs'): - - __all__.append('disk_usage') - _ntuple_diskusage = collections.namedtuple('usage', 'total used free') - _ntuple_diskusage.total.__doc__ = 'Total space in bytes' - _ntuple_diskusage.used.__doc__ = 'Used space in bytes' - _ntuple_diskusage.free.__doc__ = 'Free space in bytes' - - def disk_usage(path): - """Return disk usage statistics about the given path. - - Returned value is a named tuple with attributes 'total', 'used' and - 'free', which are the amount of total, used and free space, in bytes. - """ - st = os.statvfs(path) - free = st.f_bavail * st.f_frsize - total = st.f_blocks * st.f_frsize - used = (st.f_blocks - st.f_bfree) * st.f_frsize - return _ntuple_diskusage(total, used, free) - -elif os.name == 'nt': - - import nt - __all__.append('disk_usage') - _ntuple_diskusage = collections.namedtuple('usage', 'total used free') - - def disk_usage(path): - """Return disk usage statistics about the given path. - - Returned values is a named tuple with attributes 'total', 'used' and - 'free', which are the amount of total, used and free space, in bytes. - """ - total, free = nt._getdiskusage(path) - used = total - free - return _ntuple_diskusage(total, used, free) - - -def chown(path, user=None, group=None): - """Change owner user and group of the given path. - - user and group can be the uid/gid or the user/group names, and in that case, - they are converted to their respective uid/gid. - """ - - if user is None and group is None: - raise ValueError("user and/or group must be set") - - _user = user - _group = group - - # -1 means don't change it - if user is None: - _user = -1 - # user can either be an int (the uid) or a string (the system username) - elif isinstance(user, str): - _user = _get_uid(user) - if _user is None: - raise LookupError("no such user: {!r}".format(user)) - - if group is None: - _group = -1 - elif not isinstance(group, int): - _group = _get_gid(group) - if _group is None: - raise LookupError("no such group: {!r}".format(group)) - - os.chown(path, _user, _group) - -def get_terminal_size(fallback=(80, 24)): - """Get the size of the terminal window. - - For each of the two dimensions, the environment variable, COLUMNS - and LINES respectively, is checked. If the variable is defined and - the value is a positive integer, it is used. - - When COLUMNS or LINES is not defined, which is the common case, - the terminal connected to sys.__stdout__ is queried - by invoking os.get_terminal_size. - - If the terminal size cannot be successfully queried, either because - the system doesn't support querying, or because we are not - connected to a terminal, the value given in fallback parameter - is used. Fallback defaults to (80, 24) which is the default - size used by many terminal emulators. - - The value returned is a named tuple of type os.terminal_size. - """ - # columns, lines are the working values - try: - columns = int(os.environ['COLUMNS']) - except (KeyError, ValueError): - columns = 0 - - try: - lines = int(os.environ['LINES']) - except (KeyError, ValueError): - lines = 0 - - # only query if necessary - if columns <= 0 or lines <= 0: - try: - size = os.get_terminal_size(sys.__stdout__.fileno()) - except (AttributeError, ValueError, OSError): - # stdout is None, closed, detached, or not a terminal, or - # os.get_terminal_size() is unsupported - size = os.terminal_size(fallback) - if columns <= 0: - columns = size.columns - if lines <= 0: - lines = size.lines - - return os.terminal_size((columns, lines)) - -def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - - """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - - # If we're given a path with a directory part, look it up directly rather - # than referring to PATH directories. This includes checking relative to the - # current directory, e.g. ./script - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", None) - if path is None: - try: - path = os.confstr("CS_PATH") - except (AttributeError, ValueError): - # os.confstr() or CS_PATH is not available - path = os.defpath - # bpo-35755: Don't use os.defpath if the PATH environment variable is - # set to an empty string - - # PATH='' doesn't match, whereas PATH=':' looks in the current directory - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) - - # PATHEXT is necessary to check on Windows. - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - # See if the given file matches any of the expected path extensions. - # This will allow us to short circuit when given "python.exe". - # If it does match, only test that one, otherwise we have to try - # others. - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - # On other platforms you don't have things like PATHEXT to tell you - # what file suffixes are executable, so just pass on cmd as-is. - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if not normdir in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/LICENSE.rst b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/LICENSE.rst deleted file mode 100644 index 9d227a0..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/LICENSE.rst +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/METADATA deleted file mode 100644 index db7fcd1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/METADATA +++ /dev/null @@ -1,137 +0,0 @@ -Metadata-Version: 2.1 -Name: Flask -Version: 1.1.2 -Summary: A simple framework for building complex web applications. -Home-page: https://palletsprojects.com/p/flask/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: Pallets -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://flask.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/flask -Project-URL: Issue tracker, https://github.com/pallets/flask/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Framework :: Flask -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* -Requires-Dist: Werkzeug (>=0.15) -Requires-Dist: Jinja2 (>=2.10.1) -Requires-Dist: itsdangerous (>=0.24) -Requires-Dist: click (>=5.1) -Provides-Extra: dev -Requires-Dist: pytest ; extra == 'dev' -Requires-Dist: coverage ; extra == 'dev' -Requires-Dist: tox ; extra == 'dev' -Requires-Dist: sphinx ; extra == 'dev' -Requires-Dist: pallets-sphinx-themes ; extra == 'dev' -Requires-Dist: sphinxcontrib-log-cabinet ; extra == 'dev' -Requires-Dist: sphinx-issues ; extra == 'dev' -Provides-Extra: docs -Requires-Dist: sphinx ; extra == 'docs' -Requires-Dist: pallets-sphinx-themes ; extra == 'docs' -Requires-Dist: sphinxcontrib-log-cabinet ; extra == 'docs' -Requires-Dist: sphinx-issues ; extra == 'docs' -Provides-Extra: dotenv -Requires-Dist: python-dotenv ; extra == 'dotenv' - -Flask -===== - -Flask is a lightweight `WSGI`_ web application framework. It is designed -to make getting started quick and easy, with the ability to scale up to -complex applications. It began as a simple wrapper around `Werkzeug`_ -and `Jinja`_ and has become one of the most popular Python web -application frameworks. - -Flask offers suggestions, but doesn't enforce any dependencies or -project layout. It is up to the developer to choose the tools and -libraries they want to use. There are many extensions provided by the -community that make adding new functionality easy. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U Flask - - -A Simple Example ----------------- - -.. code-block:: python - - from flask import Flask - - app = Flask(__name__) - - @app.route("/") - def hello(): - return "Hello, World!" - -.. code-block:: text - - $ env FLASK_APP=hello.py flask run - * Serving Flask app "hello" - * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) - - -Contributing ------------- - -For guidance on setting up a development environment and how to make a -contribution to Flask, see the `contributing guidelines`_. - -.. _contributing guidelines: https://github.com/pallets/flask/blob/master/CONTRIBUTING.rst - - -Donate ------- - -The Pallets organization develops and supports Flask and the libraries -it uses. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, `please -donate today`_. - -.. _please donate today: https://psfmember.org/civicrm/contribute/transact?reset=1&id=20 - - -Links ------ - -* Website: https://palletsprojects.com/p/flask/ -* Documentation: https://flask.palletsprojects.com/ -* Releases: https://pypi.org/project/Flask/ -* Code: https://github.com/pallets/flask -* Issue tracker: https://github.com/pallets/flask/issues -* Test status: https://dev.azure.com/pallets/flask/_build -* Official chat: https://discord.gg/t6rrQZH - -.. _WSGI: https://wsgi.readthedocs.io -.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/ -.. _Jinja: https://www.palletsprojects.com/p/jinja/ -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/RECORD deleted file mode 100644 index bd83c40..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/RECORD +++ /dev/null @@ -1,48 +0,0 @@ -../../../bin/flask,sha256=0m_yeiEYqMwjqfWtGiIX5Mrm7NudN-oIDDYmqkqUvHo,271 -Flask-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -Flask-1.1.2.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 -Flask-1.1.2.dist-info/METADATA,sha256=3INpPWH6nKfZ33R2N-bQZy4TOe1wQCMweZc9mwcNrtc,4591 -Flask-1.1.2.dist-info/RECORD,, -Flask-1.1.2.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110 -Flask-1.1.2.dist-info/entry_points.txt,sha256=gBLA1aKg0OYR8AhbAfg8lnburHtKcgJLDU52BBctN0k,42 -Flask-1.1.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 -flask/__init__.py,sha256=YnA9wkwbJcnb_jTT-nMsMFeFE_UWt33khKzdHmMSuyI,1894 -flask/__main__.py,sha256=fjVtt3QTANXlpJCOv3Ha7d5H-76MwzSIOab7SFD9TEk,254 -flask/__pycache__/__init__.cpython-37.pyc,, -flask/__pycache__/__main__.cpython-37.pyc,, -flask/__pycache__/_compat.cpython-37.pyc,, -flask/__pycache__/app.cpython-37.pyc,, -flask/__pycache__/blueprints.cpython-37.pyc,, -flask/__pycache__/cli.cpython-37.pyc,, -flask/__pycache__/config.cpython-37.pyc,, -flask/__pycache__/ctx.cpython-37.pyc,, -flask/__pycache__/debughelpers.cpython-37.pyc,, -flask/__pycache__/globals.cpython-37.pyc,, -flask/__pycache__/helpers.cpython-37.pyc,, -flask/__pycache__/logging.cpython-37.pyc,, -flask/__pycache__/sessions.cpython-37.pyc,, -flask/__pycache__/signals.cpython-37.pyc,, -flask/__pycache__/templating.cpython-37.pyc,, -flask/__pycache__/testing.cpython-37.pyc,, -flask/__pycache__/views.cpython-37.pyc,, -flask/__pycache__/wrappers.cpython-37.pyc,, -flask/_compat.py,sha256=8KPT54Iig96TuLipdogLRHNYToIcg-xPhnSV5VRERnw,4099 -flask/app.py,sha256=tmEhx_XrIRP24vZg39dHMWFzJ2jj-YxIcd51LaIT5cE,98059 -flask/blueprints.py,sha256=vkdm8NusGsfZUeIfPdCluj733QFmiQcT4Sk1tuZLUjw,21400 -flask/cli.py,sha256=SIb22uq9wYBeB2tKMl0pYdhtZ1MAQyZtPL-3m6es4G0,31035 -flask/config.py,sha256=3dejvQRYfNHw_V7dCLMxU8UNFpL34xIKemN7gHZIZ8Y,10052 -flask/ctx.py,sha256=cks-omGedkxawHFo6bKIrdOHsJCAgg1i_NWw_htxb5U,16724 -flask/debughelpers.py,sha256=-whvPKuAoU8AZ9c1z_INuOeBgfYDqE1J2xNBsoriugU,6475 -flask/globals.py,sha256=OgcHb6_NCyX6-TldciOdKcyj4PNfyQwClxdMhvov6aA,1637 -flask/helpers.py,sha256=IHa578HU_3XAAo1wpXQv24MYRYO5TzaiDQQwvUIcE6Q,43074 -flask/json/__init__.py,sha256=6nITbZYiYOPB8Qfi1-dvsblwn01KRz8VOsMBIZyaYek,11988 -flask/json/__pycache__/__init__.cpython-37.pyc,, -flask/json/__pycache__/tag.cpython-37.pyc,, -flask/json/tag.py,sha256=vq9GOllg_0kTWKuVFrwmkeOQzR-jdBD23x-89JyCCQI,8306 -flask/logging.py,sha256=WcY5UkqTysGfmosyygSlXyZYGwOp3y-VsE6ehoJ48dk,3250 -flask/sessions.py,sha256=G0KsEkr_i1LG_wOINwFSOW3ts7Xbv4bNgEZKc7TRloc,14360 -flask/signals.py,sha256=yYLOed2x8WnQ7pirGalQYfpYpCILJ0LJhmNSrnWvjqw,2212 -flask/templating.py,sha256=F8E_IZXn9BGsjMzUJ5N_ACMyZdiFBp_SSEaUunvfZ7g,4939 -flask/testing.py,sha256=WXsciCQbHBP7xjHqNvOA4bT0k86GvSNpgzncfXLDEEg,10146 -flask/views.py,sha256=eeWnadLAj0QdQPLtjKipDetRZyG62CT2y7fNOFDJz0g,5802 -flask/wrappers.py,sha256=kgsvtZuMM6RQaDqhRbc5Pcj9vqTnaERl2pmXcdGL7LU,4736 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/WHEEL deleted file mode 100644 index 8b701e9..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.6) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/entry_points.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/entry_points.txt deleted file mode 100644 index 1eb0252..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -flask = flask.cli:main - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/top_level.txt deleted file mode 100644 index 7e10602..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask-1.1.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -flask diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/LICENSE b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/LICENSE deleted file mode 100644 index 46d932f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (C) 2016 Cory Dolphin, Olin College - -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. \ No newline at end of file diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/METADATA deleted file mode 100644 index b63fdd1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/METADATA +++ /dev/null @@ -1,162 +0,0 @@ -Metadata-Version: 2.1 -Name: Flask-Cors -Version: 3.0.8 -Summary: A Flask extension adding a decorator for CORS support -Home-page: https://github.com/corydolphin/flask-cors -Author: Cory Dolphin -Author-email: corydolphin@gmail.com -License: MIT -Platform: any -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Dist: Flask (>=0.9) -Requires-Dist: Six - -Flask-CORS -========== - -|Build Status| |Latest Version| |Supported Python versions| -|License| - -A Flask extension for handling Cross Origin Resource Sharing (CORS), -making cross-origin AJAX possible. - -This package has a simple philosophy, when you want to enable CORS, you -wish to enable it for all use cases on a domain. This means no mucking -around with different allowed headers, methods, etc. By default, -submission of cookies across domains is disabled due to the security -implications, please see the documentation for how to enable -credential'ed requests, and please make sure you add some sort of -`CSRF `__ -protection before doing so! - -Installation ------------- - -Install the extension with using pip, or easy\_install. - -.. code:: bash - - $ pip install -U flask-cors - -Usage ------ - -This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods. It allows parameterization of all CORS headers on a per-resource level. The package also contains a decorator, for those who prefer this approach. - -Simple Usage -~~~~~~~~~~~~ - -In the simplest case, initialize the Flask-Cors extension with default -arguments in order to allow CORS for all domains on all routes. See the -full list of options in the `documentation `__. - -.. code:: python - - - from flask import Flask - from flask_cors import CORS - - app = Flask(__name__) - CORS(app) - - @app.route("/") - def helloWorld(): - return "Hello, cross-origin-world!" - -Resource specific CORS -^^^^^^^^^^^^^^^^^^^^^^ - -Alternatively, you can specify CORS options on a resource and origin -level of granularity by passing a dictionary as the `resources` option, -mapping paths to a set of options. See the -full list of options in the `documentation `__. - -.. code:: python - - app = Flask(__name__) - cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) - - @app.route("/api/v1/users") - def list_users(): - return "user example" - -Route specific CORS via decorator -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This extension also exposes a simple decorator to decorate flask routes -with. Simply add ``@cross_origin()`` below a call to Flask's -``@app.route(..)`` to allow CORS on a given route. See the -full list of options in the `decorator documentation `__. - -.. code:: python - - @app.route("/") - @cross_origin() - def helloWorld(): - return "Hello, cross-origin-world!" - -Documentation -------------- - -For a full list of options, please see the full -`documentation `__ - -Troubleshooting ---------------- - -If things aren't working as you expect, enable logging to help understand -what is going on under the hood, and why. - -.. code:: python - - logging.getLogger('flask_cors').level = logging.DEBUG - - -Tests ------ - -A simple set of tests is included in ``test/``. To run, install nose, -and simply invoke ``nosetests`` or ``python setup.py test`` to exercise -the tests. - -Contributing ------------- - -Questions, comments or improvements? Please create an issue on -`Github `__, tweet at -`@corydolphin `__ or send me an email. -I do my best to include every contribution proposed in any way that I -can. - -Credits -------- - -This Flask extension is based upon the `Decorator for the HTTP Access -Control `__ written by Armin -Ronacher. - -.. |Build Status| image:: https://api.travis-ci.org/corydolphin/flask-cors.svg?branch=master - :target: https://travis-ci.org/corydolphin/flask-cors -.. |Latest Version| image:: https://img.shields.io/pypi/v/Flask-Cors.svg - :target: https://pypi.python.org/pypi/Flask-Cors/ -.. |Supported Python versions| image:: https://img.shields.io/pypi/pyversions/Flask-Cors.svg - :target: https://img.shields.io/pypi/pyversions/Flask-Cors.svg -.. |License| image:: http://img.shields.io/:license-mit-blue.svg - :target: https://pypi.python.org/pypi/Flask-Cors/ - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/RECORD deleted file mode 100644 index c4ada9f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/RECORD +++ /dev/null @@ -1,16 +0,0 @@ -Flask_Cors-3.0.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -Flask_Cors-3.0.8.dist-info/LICENSE,sha256=bhob3FSDTB4HQMvOXV9vLK4chG_Sp_SCsRZJWU-vvV0,1069 -Flask_Cors-3.0.8.dist-info/METADATA,sha256=WAcJQwYw0qqy43tjaa9SBNOYPCyzqayKZZwJ_RLRSi0,5368 -Flask_Cors-3.0.8.dist-info/RECORD,, -Flask_Cors-3.0.8.dist-info/WHEEL,sha256=h_aVn5OB2IERUjMbi2pucmR_zzWJtk303YXvhh60NJ8,110 -Flask_Cors-3.0.8.dist-info/top_level.txt,sha256=aWye_0QNZPp_QtPF4ZluLHqnyVLT9CPJsfiGhwqkWuo,11 -flask_cors/__init__.py,sha256=oJExwfR7yU3HAsmQ_EfL6KoLK3zq3J9HsET9r-56sfM,791 -flask_cors/__pycache__/__init__.cpython-37.pyc,, -flask_cors/__pycache__/core.cpython-37.pyc,, -flask_cors/__pycache__/decorator.cpython-37.pyc,, -flask_cors/__pycache__/extension.cpython-37.pyc,, -flask_cors/__pycache__/version.cpython-37.pyc,, -flask_cors/core.py,sha256=ZzJ4yoAhgbt-xVBqFFwsDDCzKbiyKL7PlufoVByq9ro,13895 -flask_cors/decorator.py,sha256=iiwjUi0lVeCm4OJJHY5Cvuzj2nENbUns3Iq6zqKXuss,4937 -flask_cors/extension.py,sha256=FsHOkMSMj5Zv0u_I0fgVdLh0QDUpmEvt_8Xw0qVBK-8,7427 -flask_cors/version.py,sha256=sF9np2e_SuSeS9bX2MWnkn45e-mKQh1f9lVU_kod4Yg,22 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/WHEEL deleted file mode 100644 index 78e6f69..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.4) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/top_level.txt deleted file mode 100644 index 27af988..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Flask_Cors-3.0.8.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -flask_cors diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/LICENSE.rst b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/LICENSE.rst deleted file mode 100644 index c37cae4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/LICENSE.rst +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2007 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/METADATA deleted file mode 100644 index 3d5bbb4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/METADATA +++ /dev/null @@ -1,106 +0,0 @@ -Metadata-Version: 2.1 -Name: Jinja2 -Version: 2.11.1 -Summary: A very fast and expressive template engine. -Home-page: https://palletsprojects.com/p/jinja/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: Pallets -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://jinja.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/jinja -Project-URL: Issue tracker, https://github.com/pallets/jinja/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* -Description-Content-Type: text/x-rst -Requires-Dist: MarkupSafe (>=0.23) -Provides-Extra: i18n -Requires-Dist: Babel (>=0.8) ; extra == 'i18n' - -Jinja -===== - -Jinja is a fast, expressive, extensible templating engine. Special -placeholders in the template allow writing code similar to Python -syntax. Then the template is passed data to render the final document. - -It includes: - -- Template inheritance and inclusion. -- Define and import macros within templates. -- HTML templates can use autoescaping to prevent XSS from untrusted - user input. -- A sandboxed environment can safely render untrusted templates. -- AsyncIO support for generating templates and calling async - functions. -- I18N support with Babel. -- Templates are compiled to optimized Python code just-in-time and - cached, or can be compiled ahead-of-time. -- Exceptions point to the correct line in templates to make debugging - easier. -- Extensible filters, tests, functions, and even syntax. - -Jinja's philosophy is that while application logic belongs in Python if -possible, it shouldn't make the template designer's job difficult by -restricting functionality too much. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - $ pip install -U Jinja2 - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -In A Nutshell -------------- - -.. code-block:: jinja - - {% extends "base.html" %} - {% block title %}Members{% endblock %} - {% block content %} - - {% endblock %} - - -Links ------ - -- Website: https://palletsprojects.com/p/jinja/ -- Documentation: https://jinja.palletsprojects.com/ -- Releases: https://pypi.org/project/Jinja2/ -- Code: https://github.com/pallets/jinja -- Issue tracker: https://github.com/pallets/jinja/issues -- Test status: https://dev.azure.com/pallets/jinja/_build -- Official chat: https://discord.gg/t6rrQZH - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/RECORD deleted file mode 100644 index 5a1dddb..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/RECORD +++ /dev/null @@ -1,61 +0,0 @@ -Jinja2-2.11.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -Jinja2-2.11.1.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 -Jinja2-2.11.1.dist-info/METADATA,sha256=7e9_tz7RirTbxIeiHTSq3e5g6ddCjoym3o5vdlRLuxU,3535 -Jinja2-2.11.1.dist-info/RECORD,, -Jinja2-2.11.1.dist-info/WHEEL,sha256=hq9T7ntHzQqUTLUmJ2UVhPL-W4tJi3Yb2Lh5lMfs2mk,110 -Jinja2-2.11.1.dist-info/entry_points.txt,sha256=Qy_DkVo6Xj_zzOtmErrATe8lHZhOqdjpt3e4JJAGyi8,61 -Jinja2-2.11.1.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 -jinja2/__init__.py,sha256=Nq1rzGErXYjIQnqc1pDCJht5LmInBRIZkeL2qkrYEyI,1549 -jinja2/__pycache__/__init__.cpython-37.pyc,, -jinja2/__pycache__/_compat.cpython-37.pyc,, -jinja2/__pycache__/_identifier.cpython-37.pyc,, -jinja2/__pycache__/asyncfilters.cpython-37.pyc,, -jinja2/__pycache__/asyncsupport.cpython-37.pyc,, -jinja2/__pycache__/bccache.cpython-37.pyc,, -jinja2/__pycache__/compiler.cpython-37.pyc,, -jinja2/__pycache__/constants.cpython-37.pyc,, -jinja2/__pycache__/debug.cpython-37.pyc,, -jinja2/__pycache__/defaults.cpython-37.pyc,, -jinja2/__pycache__/environment.cpython-37.pyc,, -jinja2/__pycache__/exceptions.cpython-37.pyc,, -jinja2/__pycache__/ext.cpython-37.pyc,, -jinja2/__pycache__/filters.cpython-37.pyc,, -jinja2/__pycache__/idtracking.cpython-37.pyc,, -jinja2/__pycache__/lexer.cpython-37.pyc,, -jinja2/__pycache__/loaders.cpython-37.pyc,, -jinja2/__pycache__/meta.cpython-37.pyc,, -jinja2/__pycache__/nativetypes.cpython-37.pyc,, -jinja2/__pycache__/nodes.cpython-37.pyc,, -jinja2/__pycache__/optimizer.cpython-37.pyc,, -jinja2/__pycache__/parser.cpython-37.pyc,, -jinja2/__pycache__/runtime.cpython-37.pyc,, -jinja2/__pycache__/sandbox.cpython-37.pyc,, -jinja2/__pycache__/tests.cpython-37.pyc,, -jinja2/__pycache__/utils.cpython-37.pyc,, -jinja2/__pycache__/visitor.cpython-37.pyc,, -jinja2/_compat.py,sha256=B6Se8HjnXVpzz9-vfHejn-DV2NjaVK-Iewupc5kKlu8,3191 -jinja2/_identifier.py,sha256=EdgGJKi7O1yvr4yFlvqPNEqV6M1qHyQr8Gt8GmVTKVM,1775 -jinja2/asyncfilters.py,sha256=8uwjG1zgHTv3K4nEvsj4HXWkK4NsOlfx7-CcnCULDWw,4185 -jinja2/asyncsupport.py,sha256=ZBFsDLuq3Gtji3Ia87lcyuDbqaHZJRdtShZcqwpFnSQ,7209 -jinja2/bccache.py,sha256=3Pmp4jo65M9FQuIxdxoDBbEDFwe4acDMQf77nEJfrHA,12139 -jinja2/compiler.py,sha256=xCNpF7-xAduODbGKSVEyzU7XZGeLWHZr1cwcZTQob30,66236 -jinja2/constants.py,sha256=RR1sTzNzUmKco6aZicw4JpQpJGCuPuqm1h1YmCNUEFY,1458 -jinja2/debug.py,sha256=UmsW6OxNmbIGvIkwytOyM1NsZB6xJvl_nSz3VgNETUk,8597 -jinja2/defaults.py,sha256=85B6YUUCyWPSdrSeVhcqFVuu_bHUAQXeey--FIwSeVQ,1126 -jinja2/environment.py,sha256=XqCM_GmncAXPm--CxpRPVF6uV_sPKb0Q0jVa7Znry04,50605 -jinja2/exceptions.py,sha256=VjNLawcmf2ODffqVMCQK1cRmvFaUfQWF4u8ouP3QPcE,5425 -jinja2/ext.py,sha256=AtwL5O5enT_L3HR9-oBvhGyUTdGoyaqG_ICtnR_EVd4,26441 -jinja2/filters.py,sha256=4xEq1qfJ7burpHW5GyL6bkGomp0W47jOXg-HG5aLP-Y,41401 -jinja2/idtracking.py,sha256=J3O4VHsrbf3wzwiBc7Cro26kHb6_5kbULeIOzocchIU,9211 -jinja2/lexer.py,sha256=VeGdW_t82Le4H-jLy-hX6UeosLf7ApUq2kuUos8YF4Y,29942 -jinja2/loaders.py,sha256=UUy5ud3lNtGtnn8iorlF9o1FJ6UqZZKMxd0VGnnqMHI,20350 -jinja2/meta.py,sha256=QjyYhfNRD3QCXjBJpiPl9KgkEkGXJbAkCUq4-Ur10EQ,4131 -jinja2/nativetypes.py,sha256=Arb2_3IuM386vWZbGPY7DmxryrXg3WzXAEnaHJNdWa0,3576 -jinja2/nodes.py,sha256=YwErhE9plVWeoxTQPtMwl10wovsyBRY4x9eAVgtP6zg,31071 -jinja2/optimizer.py,sha256=gQLlMYzvQhluhzmAIFA1tXS0cwgWYOjprN-gTRcHVsc,1457 -jinja2/parser.py,sha256=fcfdqePNTNyvosIvczbytVA332qpsURvYnCGcjDHSkA,35660 -jinja2/runtime.py,sha256=94chnK20a1m1t5AaLWeuiTq6L3g3GLs6AxVPfbNXIHE,30582 -jinja2/sandbox.py,sha256=knayyUvXsZ-F0mk15mO2-ehK9gsw04UhB8td-iUOtLc,17127 -jinja2/tests.py,sha256=iO_Y-9Vo60zrVe1lMpSl5sKHqAxe2leZHC08OoZ8K24,4799 -jinja2/utils.py,sha256=26B9HI2lVWaHY8iOnQTJzAcCL4PYOLiA3V79dm3oOSE,22456 -jinja2/visitor.py,sha256=DUHupl0a4PGp7nxRtZFttUzAi1ccxzqc2hzetPYUz8U,3240 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/WHEEL deleted file mode 100644 index 03bcde7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/entry_points.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/entry_points.txt deleted file mode 100644 index 3619483..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[babel.extractors] -jinja2 = jinja2.ext:babel_extract [i18n] - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/top_level.txt deleted file mode 100644 index 7f7afbf..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Jinja2-2.11.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -jinja2 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt deleted file mode 100644 index 9d227a0..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA deleted file mode 100644 index b208d93..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA +++ /dev/null @@ -1,103 +0,0 @@ -Metadata-Version: 2.1 -Name: MarkupSafe -Version: 1.1.1 -Summary: Safely add untrusted strings to HTML/XML markup. -Home-page: https://palletsprojects.com/p/markupsafe/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: The Pallets Team -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://markupsafe.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/markupsafe -Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* - -MarkupSafe -========== - -MarkupSafe implements a text object that escapes characters so it is -safe to use in HTML and XML. Characters that have special meanings are -replaced so that they display as the actual characters. This mitigates -injection attacks, meaning untrusted user input can safely be displayed -on a page. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U MarkupSafe - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -Examples --------- - -.. code-block:: pycon - - >>> from markupsafe import Markup, escape - >>> # escape replaces special characters and wraps in Markup - >>> escape('') - Markup(u'<script>alert(document.cookie);</script>') - >>> # wrap in Markup to mark text "safe" and prevent escaping - >>> Markup('Hello') - Markup('hello') - >>> escape(Markup('Hello')) - Markup('hello') - >>> # Markup is a text subclass (str on Python 3, unicode on Python 2) - >>> # methods and operators escape their arguments - >>> template = Markup("Hello %s") - >>> template % '"World"' - Markup('Hello "World"') - - -Donate ------- - -The Pallets organization develops and supports MarkupSafe and other -libraries that use it. In order to grow the community of contributors -and users, and allow the maintainers to devote more time to the -projects, `please donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -* Website: https://palletsprojects.com/p/markupsafe/ -* Documentation: https://markupsafe.palletsprojects.com/ -* License: `BSD-3-Clause `_ -* Releases: https://pypi.org/project/MarkupSafe/ -* Code: https://github.com/pallets/markupsafe -* Issue tracker: https://github.com/pallets/markupsafe/issues -* Test status: - - * Linux, Mac: https://travis-ci.org/pallets/markupsafe - * Windows: https://ci.appveyor.com/project/pallets/markupsafe - -* Test coverage: https://codecov.io/gh/pallets/markupsafe - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD deleted file mode 100644 index 207f391..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD +++ /dev/null @@ -1,16 +0,0 @@ -MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -MarkupSafe-1.1.1.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 -MarkupSafe-1.1.1.dist-info/METADATA,sha256=nJHwJ4_4ka-V39QH883jPrslj6inNdyyNASBXbYgHXQ,3570 -MarkupSafe-1.1.1.dist-info/RECORD,, -MarkupSafe-1.1.1.dist-info/WHEEL,sha256=AhV6RMqZ2IDfreRJKo44QWYxYeP-0Jr0bezzBLQ1eog,109 -MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 -markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126 -markupsafe/__pycache__/__init__.cpython-37.pyc,, -markupsafe/__pycache__/_compat.cpython-37.pyc,, -markupsafe/__pycache__/_constants.cpython-37.pyc,, -markupsafe/__pycache__/_native.cpython-37.pyc,, -markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558 -markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690 -markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873 -markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884 -markupsafe/_speedups.cpython-37m-x86_64-linux-gnu.so,sha256=pz-ucGdAq6kJtq9lEY1kY2Ed6LQjbRrIicdu_i4HFqU,38875 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL deleted file mode 100644 index 697e432..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.31.1) -Root-Is-Purelib: false -Tag: cp37-cp37m-manylinux1_x86_64 - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt deleted file mode 100644 index 75bf729..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -markupsafe diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/LICENSE.rst b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/LICENSE.rst deleted file mode 100644 index c37cae4..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/LICENSE.rst +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2007 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/METADATA deleted file mode 100644 index eb5f709..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/METADATA +++ /dev/null @@ -1,128 +0,0 @@ -Metadata-Version: 2.1 -Name: Werkzeug -Version: 1.0.1 -Summary: The comprehensive WSGI web application library. -Home-page: https://palletsprojects.com/p/werkzeug/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: Pallets -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://werkzeug.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/werkzeug -Project-URL: Issue tracker, https://github.com/pallets/werkzeug/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* -Description-Content-Type: text/x-rst -Provides-Extra: dev -Requires-Dist: pytest ; extra == 'dev' -Requires-Dist: pytest-timeout ; extra == 'dev' -Requires-Dist: coverage ; extra == 'dev' -Requires-Dist: tox ; extra == 'dev' -Requires-Dist: sphinx ; extra == 'dev' -Requires-Dist: pallets-sphinx-themes ; extra == 'dev' -Requires-Dist: sphinx-issues ; extra == 'dev' -Provides-Extra: watchdog -Requires-Dist: watchdog ; extra == 'watchdog' - -Werkzeug -======== - -*werkzeug* German noun: "tool". Etymology: *werk* ("work"), *zeug* ("stuff") - -Werkzeug is a comprehensive `WSGI`_ web application library. It began as -a simple collection of various utilities for WSGI applications and has -become one of the most advanced WSGI utility libraries. - -It includes: - -- An interactive debugger that allows inspecting stack traces and - source code in the browser with an interactive interpreter for any - frame in the stack. -- A full-featured request object with objects to interact with - headers, query args, form data, files, and cookies. -- A response object that can wrap other WSGI applications and handle - streaming data. -- A routing system for matching URLs to endpoints and generating URLs - for endpoints, with an extensible system for capturing variables - from URLs. -- HTTP utilities to handle entity tags, cache control, dates, user - agents, cookies, files, and more. -- A threaded WSGI server for use while developing applications - locally. -- A test client for simulating HTTP requests during testing without - requiring running a server. - -Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up -to the developer to choose a template engine, database adapter, and even -how to handle requests. It can be used to build all sorts of end user -applications such as blogs, wikis, or bulletin boards. - -`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while -providing more structure and patterns for defining powerful -applications. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U Werkzeug - - -A Simple Example ----------------- - -.. code-block:: python - - from werkzeug.wrappers import Request, Response - - @Request.application - def application(request): - return Response('Hello, World!') - - if __name__ == '__main__': - from werkzeug.serving import run_simple - run_simple('localhost', 4000, application) - - -Links ------ - -- Website: https://palletsprojects.com/p/werkzeug/ -- Documentation: https://werkzeug.palletsprojects.com/ -- Releases: https://pypi.org/project/Werkzeug/ -- Code: https://github.com/pallets/werkzeug -- Issue tracker: https://github.com/pallets/werkzeug/issues -- Test status: https://dev.azure.com/pallets/werkzeug/_build -- Official chat: https://discord.gg/t6rrQZH - -.. _WSGI: https://wsgi.readthedocs.io/en/latest/ -.. _Flask: https://www.palletsprojects.com/p/flask/ -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/RECORD deleted file mode 100644 index 7599806..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/RECORD +++ /dev/null @@ -1,101 +0,0 @@ -Werkzeug-1.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -Werkzeug-1.0.1.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 -Werkzeug-1.0.1.dist-info/METADATA,sha256=d0zmVNa4UC2-nAo2A8_81oiy123D6JTGRSuY_Ymgyt4,4730 -Werkzeug-1.0.1.dist-info/RECORD,, -Werkzeug-1.0.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 -Werkzeug-1.0.1.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 -werkzeug/__init__.py,sha256=rb-yPiXOjTLbtDOl5fQp5hN7oBdaoXAoQ-slAAvfZAo,502 -werkzeug/__pycache__/__init__.cpython-37.pyc,, -werkzeug/__pycache__/_compat.cpython-37.pyc,, -werkzeug/__pycache__/_internal.cpython-37.pyc,, -werkzeug/__pycache__/_reloader.cpython-37.pyc,, -werkzeug/__pycache__/datastructures.cpython-37.pyc,, -werkzeug/__pycache__/exceptions.cpython-37.pyc,, -werkzeug/__pycache__/filesystem.cpython-37.pyc,, -werkzeug/__pycache__/formparser.cpython-37.pyc,, -werkzeug/__pycache__/http.cpython-37.pyc,, -werkzeug/__pycache__/local.cpython-37.pyc,, -werkzeug/__pycache__/posixemulation.cpython-37.pyc,, -werkzeug/__pycache__/routing.cpython-37.pyc,, -werkzeug/__pycache__/security.cpython-37.pyc,, -werkzeug/__pycache__/serving.cpython-37.pyc,, -werkzeug/__pycache__/test.cpython-37.pyc,, -werkzeug/__pycache__/testapp.cpython-37.pyc,, -werkzeug/__pycache__/urls.cpython-37.pyc,, -werkzeug/__pycache__/useragents.cpython-37.pyc,, -werkzeug/__pycache__/utils.cpython-37.pyc,, -werkzeug/__pycache__/wsgi.cpython-37.pyc,, -werkzeug/_compat.py,sha256=zjufTNrhQ8BgYSGSh-sVu6iW3r3O9WzjE9j-qJobx-g,6671 -werkzeug/_internal.py,sha256=d_4AqheyS6dHMViwdc0drFrjs67ZzT6Ej2gWf-Z-Iys,14351 -werkzeug/_reloader.py,sha256=I3mg3oRQ0lLzl06oEoVopN3bN7CtINuuUQdqDcmTnEs,11531 -werkzeug/datastructures.py,sha256=AonxOcwU0TPMEzfKF1368ySULxHgxE-JE-DEAGdo2ts,100480 -werkzeug/debug/__init__.py,sha256=3RtUMc5Y9hYyK11ugHltgkQ9Dt-ViR945Vy_X5NV7zU,17289 -werkzeug/debug/__pycache__/__init__.cpython-37.pyc,, -werkzeug/debug/__pycache__/console.cpython-37.pyc,, -werkzeug/debug/__pycache__/repr.cpython-37.pyc,, -werkzeug/debug/__pycache__/tbtools.cpython-37.pyc,, -werkzeug/debug/console.py,sha256=OATaO7KHYMqpbzIFe1HeW9Mnl3wZgA3jMQoGDPn5URc,5488 -werkzeug/debug/repr.py,sha256=lIwuhbyrMwVe3P_cFqNyqzHL7P93TLKod7lw9clydEw,9621 -werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 -werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 -werkzeug/debug/shared/debugger.js,sha256=rOhqZMRfpZnnu6_XCGn6wMWPhtfwRAcyZKksdIxPJas,6400 -werkzeug/debug/shared/jquery.js,sha256=CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo,88145 -werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 -werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 -werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 -werkzeug/debug/shared/style.css,sha256=gZ9uhmb5zj3XLuT9RvnMp6jMINgQ-VVBCp-2AZbG3YQ,6604 -werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 -werkzeug/debug/tbtools.py,sha256=2iJ8RURUZUSbopOIehy53LnVJWx47lsHN2V2l6hc7Wc,20363 -werkzeug/exceptions.py,sha256=UTYSDkmAsH-vt8VSidlEffwqBVNXuT7bRg-_NqgUe8A,25188 -werkzeug/filesystem.py,sha256=HzKl-j0Hd8Jl66j778UbPTAYNnY6vUZgYLlBZ0e7uw0,2101 -werkzeug/formparser.py,sha256=Sto0jZid9im9ZVIf56vilCdyX-arK33wSftkYsLCnzo,21788 -werkzeug/http.py,sha256=KVRV3yFK14PJeI56qClEq4qxFdvKUQVy4C_dwuWz9_Q,43107 -werkzeug/local.py,sha256=_Tk7gB238pPWUU7habxFkZF02fiCMRVW6d62YWL1Rh0,14371 -werkzeug/middleware/__init__.py,sha256=f1SFZo67IlW4k1uqKzNHxYQlsakUS-D6KK_j0e3jjwQ,549 -werkzeug/middleware/__pycache__/__init__.cpython-37.pyc,, -werkzeug/middleware/__pycache__/dispatcher.cpython-37.pyc,, -werkzeug/middleware/__pycache__/http_proxy.cpython-37.pyc,, -werkzeug/middleware/__pycache__/lint.cpython-37.pyc,, -werkzeug/middleware/__pycache__/profiler.cpython-37.pyc,, -werkzeug/middleware/__pycache__/proxy_fix.cpython-37.pyc,, -werkzeug/middleware/__pycache__/shared_data.cpython-37.pyc,, -werkzeug/middleware/dispatcher.py,sha256=_-KoMzHtcISHS7ouWKAOraqlCLprdh83YOAn_8DjLp8,2240 -werkzeug/middleware/http_proxy.py,sha256=lRjTdMmghHiZuZrS7_UJ3gZc-vlFizhBbFZ-XZPLwIA,7117 -werkzeug/middleware/lint.py,sha256=ItTwuWJnflF8xMT1uqU_Ty1ryhux-CjeUfskqaUpxsw,12967 -werkzeug/middleware/profiler.py,sha256=8B_s23d6BGrU_q54gJsm6kcCbOJbTSqrXCsioHON0Xs,4471 -werkzeug/middleware/proxy_fix.py,sha256=K5oZ3DPXOzdZi0Xba5zW7ClPOxgUuqXHQHvY2-AWCGw,6431 -werkzeug/middleware/shared_data.py,sha256=sPSRTKqtKSVBUyN8fr6jOJbdq9cdOLu6pg3gz4Y_1Xo,9599 -werkzeug/posixemulation.py,sha256=gSSiv1SCmOyzOM_nq1ZaZCtxP__C5MeDJl_4yXJmi4Q,3541 -werkzeug/routing.py,sha256=6-iZ7CKeUILYAehoKXLbmi5E6LgLbwuzUh8TNplnf5Q,79019 -werkzeug/security.py,sha256=81149MplFq7-hD4RK4sKp9kzXXejjV9D4lWBzaRyeQ8,8106 -werkzeug/serving.py,sha256=YvTqvurA-Mnj8mkqRe2kBdVr2ap4ibCq1ByQjOA6g1w,38694 -werkzeug/test.py,sha256=GJ9kxTMSJ-nB7kfGtxuROr9JGmXxDRev-2U1SkeUJGE,39564 -werkzeug/testapp.py,sha256=bHekqMsqRfVxwgFbvOMem-DYa_sdB7R47yUXpt1RUTo,9329 -werkzeug/urls.py,sha256=T8-hV_1vwhu6xhX93FwsHteK-W-kIE2orj5WoMf-WFw,39322 -werkzeug/useragents.py,sha256=TSoGv5IOvP375eK5gLLpsLQCeUgTR6sO1WftmAP_YvM,5563 -werkzeug/utils.py,sha256=hrVK4u_wi8z9viBO9bgOLlm1aaIvCpn-p2d1FeZQDEo,25251 -werkzeug/wrappers/__init__.py,sha256=S4VioKAmF_av9Ec9zQvG71X1EOkYfPx1TYck9jyDiyY,1384 -werkzeug/wrappers/__pycache__/__init__.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/accept.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/auth.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/base_request.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/base_response.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/common_descriptors.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/cors.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/etag.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/json.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/request.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/response.cpython-37.pyc,, -werkzeug/wrappers/__pycache__/user_agent.cpython-37.pyc,, -werkzeug/wrappers/accept.py,sha256=TIvjUc0g73fhTWX54wg_D9NNzKvpnG1X8u1w26tK1o8,1760 -werkzeug/wrappers/auth.py,sha256=Pmn6iaGHBrUyHbJpW0lZhO_q9RVoAa5QalaTqcavdAI,1158 -werkzeug/wrappers/base_request.py,sha256=4TuGlKWeKQdlq4eU94hJYcXSfWo8Rk7CS1Ef5lJ3ZM0,26012 -werkzeug/wrappers/base_response.py,sha256=JTxJZ8o-IBetpoWJqt2HFwPaNWNDAlM3_GXJe1Whw80,27784 -werkzeug/wrappers/common_descriptors.py,sha256=X2Ktd5zUWsmcd4ciaF62Dd8Lru9pLGP_XDUNukc8cXs,12829 -werkzeug/wrappers/cors.py,sha256=XMbaCol4dWTGvb-dCJBoN0p3JX91v93AIAHd7tnB3L4,3466 -werkzeug/wrappers/etag.py,sha256=XMXtyfByBsOjxwaX8U7ZtUY7JXkbQLP45oXZ0qkyTNs,12217 -werkzeug/wrappers/json.py,sha256=HvK_A4NpO0sLqgb10sTJcoZydYOwyNiPCJPV7SVgcgE,4343 -werkzeug/wrappers/request.py,sha256=QbHGqDpGPN684pnOPEokwkPESfm-NnfYM7ydOMxW_NI,1514 -werkzeug/wrappers/response.py,sha256=Oqv8TMG_dnOKTq_V30ddgkO5B7IJhkVPODvm7cbhZ3c,2524 -werkzeug/wrappers/user_agent.py,sha256=YJb-vr12cujG7sQMG9V89VsJa-03SWSenhg1W4cT0EY,435 -werkzeug/wsgi.py,sha256=ZGk85NzRyQTzkYis-xl8V9ydJgfClBdStvhzDzER2mw,34367 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/WHEEL deleted file mode 100644 index ef99c6c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/top_level.txt deleted file mode 100644 index 6fe8da8..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/Werkzeug-1.0.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -werkzeug diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/easy_install.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/easy_install.cpython-37.pyc deleted file mode 100644 index 54766f982a07d94555d3053e40d131188c80ec22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 281 zcmZ?b<>g`kf*i(~adklYF^B^LOhASM5Em-}i4=w?hE&EB#%!h{xfG@p<{YM6<|t-H zhE(Qe21bSymS6@=)+*_s(maKdj8p~J#NtZNyyB9?oE(MZ{M_8cyp&rU@$tEdnR)T? zFM-A}Xfobn0df5_S#Gh%$EV~c$H#+|Yp=7pIn#7L?@Y=M?Kf4bV#k8XBJo zF|~*pXvRv0A~qleCVrXdm*f`c7i1RbLY3&2 TPO2Rv(4by{b diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/six.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/__pycache__/six.cpython-37.pyc deleted file mode 100644 index 24971f37e28ce73fe4c5893b6067cf47e843f07e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26835 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 S3u=wyqkIWa61Z@i;;#U&0(oEn diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/LICENSE.rst b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/LICENSE.rst deleted file mode 100644 index d12a849..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/LICENSE.rst +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2014 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/METADATA deleted file mode 100644 index fa4536d..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/METADATA +++ /dev/null @@ -1,102 +0,0 @@ -Metadata-Version: 2.1 -Name: click -Version: 7.1.1 -Summary: Composable command line interface toolkit -Home-page: https://palletsprojects.com/p/click/ -Maintainer: Pallets -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://click.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/click -Project-URL: Issue tracker, https://github.com/pallets/click/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 3 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* - -\$ click\_ -========== - -Click is a Python package for creating beautiful command line interfaces -in a composable way with as little code as necessary. It's the "Command -Line Interface Creation Kit". It's highly configurable but comes with -sensible defaults out of the box. - -It aims to make the process of writing command line tools quick and fun -while also preventing any frustration caused by the inability to -implement an intended CLI API. - -Click in three points: - -- Arbitrary nesting of commands -- Automatic help page generation -- Supports lazy loading of subcommands at runtime - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - $ pip install -U click - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -A Simple Example ----------------- - -.. code-block:: python - - import click - - @click.command() - @click.option("--count", default=1, help="Number of greetings.") - @click.option("--name", prompt="Your name", help="The person to greet.") - def hello(count, name): - """Simple program that greets NAME for a total of COUNT times.""" - for _ in range(count): - click.echo(f"Hello, {name}!") - - if __name__ == '__main__': - hello() - -.. code-block:: text - - $ python hello.py --count=3 - Your name: Click - Hello, Click! - Hello, Click! - Hello, Click! - - -Donate ------- - -The Pallets organization develops and supports Click and other popular -packages. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, `please -donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -- Website: https://palletsprojects.com/p/click/ -- Documentation: https://click.palletsprojects.com/ -- Releases: https://pypi.org/project/click/ -- Code: https://github.com/pallets/click -- Issue tracker: https://github.com/pallets/click/issues -- Test status: https://dev.azure.com/pallets/click/_build -- Official chat: https://discord.gg/t6rrQZH - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/RECORD deleted file mode 100644 index c52207f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/RECORD +++ /dev/null @@ -1,40 +0,0 @@ -click-7.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click-7.1.1.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 -click-7.1.1.dist-info/METADATA,sha256=qGBq4nyx59fI9CN-NY-C_ye4USndxpKszWFLe5KMhQM,2868 -click-7.1.1.dist-info/RECORD,, -click-7.1.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 -click-7.1.1.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 -click/__init__.py,sha256=_Mora-ZWjo_kRK3mg_vX3ZmQV3pop8vrCLj-C209TvQ,2463 -click/__pycache__/__init__.cpython-37.pyc,, -click/__pycache__/_bashcomplete.cpython-37.pyc,, -click/__pycache__/_compat.cpython-37.pyc,, -click/__pycache__/_termui_impl.cpython-37.pyc,, -click/__pycache__/_textwrap.cpython-37.pyc,, -click/__pycache__/_unicodefun.cpython-37.pyc,, -click/__pycache__/_winconsole.cpython-37.pyc,, -click/__pycache__/core.cpython-37.pyc,, -click/__pycache__/decorators.cpython-37.pyc,, -click/__pycache__/exceptions.cpython-37.pyc,, -click/__pycache__/formatting.cpython-37.pyc,, -click/__pycache__/globals.cpython-37.pyc,, -click/__pycache__/parser.cpython-37.pyc,, -click/__pycache__/termui.cpython-37.pyc,, -click/__pycache__/testing.cpython-37.pyc,, -click/__pycache__/types.cpython-37.pyc,, -click/__pycache__/utils.cpython-37.pyc,, -click/_bashcomplete.py,sha256=9J98IHQYmCAr2Jup6TDshUr5FJEen-AoQCZR0K5nKxQ,12309 -click/_compat.py,sha256=CCA3QaccPgx3TL3biRljHNnqELqCSMr3wPIe1kXaOcQ,24257 -click/_termui_impl.py,sha256=w2Fgse5XiOSjV72IZLBKG0loK_Q1oogvh9e0spJpRAY,20793 -click/_textwrap.py,sha256=ajCzkzFly5tjm9foQ5N9_MOeaYJMBjAltuFa69n4iXY,1197 -click/_unicodefun.py,sha256=apLSNEBZgUsQNPMUv072zJ1swqnm0dYVT5TqcIWTt6w,4201 -click/_winconsole.py,sha256=6YDu6Rq1Wxx4w9uinBMK2LHvP83aerZM9GQurlk3QDo,10010 -click/core.py,sha256=V6DJzastGhrC6WTDwV9MSLwcJUdX2Uf1ypmgkjBdn_Y,77650 -click/decorators.py,sha256=3TvEO_BkaHl7k6Eh1G5eC7JK4LKPdpFqH9JP0QDyTlM,11215 -click/exceptions.py,sha256=3pQAyyMFzx5A3eV0Y27WtDTyGogZRbrC6_o5DjjKBbw,8118 -click/formatting.py,sha256=Wb4gqFEpWaKPgAbOvnkCl8p-bEZx5KpM5ZSByhlnJNk,9281 -click/globals.py,sha256=ht7u2kUGI08pAarB4e4yC8Lkkxy6gJfRZyzxEj8EbWQ,1501 -click/parser.py,sha256=mFK-k58JtPpqO0AC36WAr0t5UfzEw1mvgVSyn7WCe9M,15691 -click/termui.py,sha256=G7QBEKIepRIGLvNdGwBTYiEtSImRxvTO_AglVpyHH2s,23998 -click/testing.py,sha256=EUEsDUqNXFgCLhZ0ZFOROpaVDA5I_rijwnNPE6qICgA,12854 -click/types.py,sha256=wuubik4VqgqAw5dvbYFkDt-zSAx97y9TQXuXcVaRyQA,25045 -click/utils.py,sha256=4VEcJ7iEHwjnFuzEuRtkT99o5VG3zqSD7Q2CVzv13WU,15940 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/WHEEL deleted file mode 100644 index ef99c6c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/top_level.txt deleted file mode 100644 index dca9a90..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click-7.1.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -click diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__init__.py deleted file mode 100644 index 3910b80..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__init__.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Click is a simple Python module inspired by the stdlib optparse to make -writing command line scripts fun. Unlike other modules, it's based -around a simple API that does not come with too much magic and is -composable. -""" -from .core import Argument -from .core import BaseCommand -from .core import Command -from .core import CommandCollection -from .core import Context -from .core import Group -from .core import MultiCommand -from .core import Option -from .core import Parameter -from .decorators import argument -from .decorators import command -from .decorators import confirmation_option -from .decorators import group -from .decorators import help_option -from .decorators import make_pass_decorator -from .decorators import option -from .decorators import pass_context -from .decorators import pass_obj -from .decorators import password_option -from .decorators import version_option -from .exceptions import Abort -from .exceptions import BadArgumentUsage -from .exceptions import BadOptionUsage -from .exceptions import BadParameter -from .exceptions import ClickException -from .exceptions import FileError -from .exceptions import MissingParameter -from .exceptions import NoSuchOption -from .exceptions import UsageError -from .formatting import HelpFormatter -from .formatting import wrap_text -from .globals import get_current_context -from .parser import OptionParser -from .termui import clear -from .termui import confirm -from .termui import echo_via_pager -from .termui import edit -from .termui import get_terminal_size -from .termui import getchar -from .termui import launch -from .termui import pause -from .termui import progressbar -from .termui import prompt -from .termui import secho -from .termui import style -from .termui import unstyle -from .types import BOOL -from .types import Choice -from .types import DateTime -from .types import File -from .types import FLOAT -from .types import FloatRange -from .types import INT -from .types import IntRange -from .types import ParamType -from .types import Path -from .types import STRING -from .types import Tuple -from .types import UNPROCESSED -from .types import UUID -from .utils import echo -from .utils import format_filename -from .utils import get_app_dir -from .utils import get_binary_stream -from .utils import get_os_args -from .utils import get_text_stream -from .utils import open_file - -# Controls if click should emit the warning about the use of unicode -# literals. -disable_unicode_literals_warning = False - -__version__ = "7.1.1" diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 92cba269f5b8acfc879615ddb284728ddba05183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2696 zcmd7U$yOUj6b4`ck`R)Z2Q!*B7-J@h(afV5ZKh*ja~J8;>Mo=TJ)NqSF@A)+K~`Dk zm9)(&uaH&ly+Yu;LGbbKud2JMx^5Se4_aH(G5paDzyI<_ODy&mHR?Z&h&}wPmz!cS zCk8R6!D)0GyhdnjAUC0#potwv$05#6pc9Z_C(%hrvYXM((9BMuQ;=e}pj)7Yokpi2 z&Ca+PFAG_A7TpT1>{fIew6WXJ?a<{Q! zm}O6*=U|Tg5uJk^dkUS0JbM~F5A*C9^a3ofXVHtW$eu$l!4f-%UWR3M9=!r9?0NT- zw+gH51@s!Mu@}+nu+CmWZ@>n78NCUc>=pDDY_UI~w_%&Tir#@8_8NK@cG>IbJ=kM! zp!Z>)y@@`61NIiW00s6o`VbD;JMNKp49DzU^a-4>_t2+s%HBtx!5RAi{TV*93+ONK zg?)%Vhja81TsX&Y>73lercQrU(*;-B4~Eo+WoYSzt}w2jqH^FHUf@))C4C)AB^;yp zWJG0Q=*V$p(FnpQw3HS`6d0cMAkvRYM$#`CcHnuI?-;K1@n&1eFw(|-#m^aczAGPu z5#TK9d3HT($Y@d?{ zwm~aOoyO~7psk`Sa_PSt@Uvm6p_SpsXmM$&)VwvwRIFeSXXow}axZcvn05F;LFyd~M%^ z(*Ip~zZfXmV8?;w)GKwTt&+gLHtefyuilfzo}ahb#>eOAyDjQlX*rgzI8urqwBtf* zji=)0A=%5|24CDu+0s0BeMIXi7T`Fb3e^hP@~EuPeBNGnNkpbyQ3_wD`MT?DZ8BU% zbMX_lD=aD$R-VgEdl7ayFuzF)%UR;P;=+-%^G=!+7xScVxu%vsXzR_`X_tADq-#}t zyNsQQ(5h&%h0VldUAQ9ieG2^;OgoeuO$oRK-zRMb!bK6 zR(j+(6^=$8pI`0YBGSihU`1aopWj8(*(G(R&it3I+JU=$3VHao711*$Z*ISyU7pZH zw-x+#Mr7_TufJXuj&5#_4zU@(yF255pC7gTp380CZRsvBJ=FB$bgXRK)VA zCsRjCSYG{}K%02bH8$I8Rs0^k-q8|-!sls^eTqi&0IB z`eD_ok9yxw^ivE_3{nhH3{#9yyv2ZYtxWVGr$(vQz`%3j21U!&>K(O`As<0Ch7Cy4 znW{)Njt%vmVuIoW#U#Z?iYba|iW!PoiaClLMINJ?i0~C_HBTK26pIu~6w4GV6rU(o zDb^^~DK;oJDYhuKF{+75B=K=~sAHF6k7A$VfTBQghyjKp`J>dV_|gs>VY(7`gnKm~ zE#+ewsu|O)f1sFu#?%E3rTAwtA9-Oul;K>(4=wvaICGC>A>28AZ$FgQSA)DwUpslz gl)j8iGZ#KpQ(LufoE>`m`ZtVtL-zmhCmwJ77a32>FaQ7m diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_bashcomplete.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_bashcomplete.cpython-37.pyc deleted file mode 100644 index cb55e4a6abdfbefec81acaaa0e41076726a4c880..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9938 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_compat.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_compat.cpython-37.pyc deleted file mode 100644 index 61a66fa6bff223bcd02f77e400a01dad22274dc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18587 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 BtMUK< diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_termui_impl.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_termui_impl.cpython-37.pyc deleted file mode 100644 index 0ac1110bebe4c281da2cfc39870fd5381f647b31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14137 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_winconsole.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/_winconsole.cpython-37.pyc deleted file mode 100644 index 03b1aeaf01f78751bda34308b1f1a8fd4cbadd3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9366 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 +D5yv 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]sih*>l<#+;DKZ1kMm3WgS(p)fN0MA9sRHT_&q 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 AiU0rr diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/exceptions.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/exceptions.cpython-37.pyc deleted file mode 100644 index f66d8a641a3f742d72eb0e67ab8098d34cde64c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9031 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 Zb^O_Gv+H$V>Au!|w|ljFp}UIY{2%B&4+sDN diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/formatting.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/formatting.cpython-37.pyc deleted file mode 100644 index 9605a3c59c2b3d6acd560856caa042b1b8c5f7af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8662 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/globals.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/globals.cpython-37.pyc deleted file mode 100644 index 3d1cbd3ff1346107f73eea2489c3d34d41bb675c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1833 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/testing.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/testing.cpython-37.pyc deleted file mode 100644 index 9dc76c311dd33440877f2d18f610333c4b304fa7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11635 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 Vr0mZu=nL3zHFN2?%IZ?%e*g^Gcv=7e diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/types.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/types.cpython-37.pyc deleted file mode 100644 index ab289e8d946b826b9d88ab32fca01d85ad825bac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22375 zcmeHvO>i7XmR?u&4+@P22!P;^C~~I65r0}kKpf3@W{j0(h@haMMs8{eNR)bZrcvxF z00ne+wX&*7q6MrSqSm9acXnrI9UHL`vun^3p0yqJ#vXidIDGKQCm$S+@Ej^O!jAC4 zUWa}0-gL3Q?`2hWHwcQfI0r}AAS*kwDl7Bl%a{3n^1Zq?Ia$u(FEsw}2misz<^D4Z z>0bevC0yaZF>*OK=NheCUH=+&17)*iw#~X}LtmK zAwO0hle~qzRktKRj{JCiT=He)%k{G4Ct4HjO1&caN^7z`RiBdlB=X1V$Bf*YId{rE z_DRk?=1o7y*Jn_kc4ttY@n%q-MS0dej`DFSA4hr4J%REGDbJyN(mjRpDJh>o`Lz2S z%FjvpB+6&p=TUxM%BN61>z+gToRm+a{3Z9xD1X^IjsBiP*>+z*`2~4?2IceaS5W?n zcLvX&NBKqf0?HTU`B{`Nx|dMCB;|7`Uv{e~SEc+VlwWecit<;b{AHA{xbrB_d$VZI zcCWe%?#rJT^%uOk2f6xr?*!7X0G3?+Mf8}fU+~T%z381oddW3bbJef?1!uQbHDb$k zA}{jW-d|vLbGR|v*z}@?qc-n0yiPN4{mv%tPHp%tuj916Miex9KJJ`iHQo((!^mq7 zSDxgfFjAhURG?6IBItS@x#P4^%)j%&EBG0Yy!%lj+U&#b}Q~Aeka@+p(3MRar3~?Y&#N zEWv5D5EnwPwGkJE65^taB+fUZ`~Ntn=Frk-FTWhMyDxYB?tHJ)b(%Y#I}eDx)_l0p z+}ZrA-wIxCw*2PK%bIq&yRp@1kk}iID}+WsG%TY(o6+M!TA^v82LJfW^(*l64O!)8 z|Fv6Q)KeW&i)UkLId>fev~M_^S(0)@glg>j8zjE23hrVGLmP-+sL2SbrkX~RYL*Fy zq>~fK#S>iWNyArhBNT{?{)qvwLp7cVZ*;R8`9TMx-?iKR=2iqMU?p1Zhczp`*OqlqVv^04FAzpOVDJxxMLvWH-5@V^s)q&s&55ROb)w&ge& zzS27c2dUSJeOabjL!h^(>R|oo`7G%9oZ(c;q#kE(bY|5t+*{1XSm@6T#+cCl$ZY0O zRj7}ovS)Nlu7Q=4+cq9@jHc7Wz~A)mVx`K)*TeoOyAh_gbJtfvr;Qy0@G4*L4y4Pl z+u}w9s_b>M+44KsIl?wb#BOf&Iy)ig8Qg_@3N$N(4g&W(z!q92y|?@@(rt}W#f=TA zExq6gaUFWt@PY)DSFp4A%`L1OM^+HV5h%CVcfG(uVRfuTwo7xW#cjXQ-ksFQPr%~{v^lkRZSt`G7Wjl zsuavZzF-y1a>2@5V^+y3ON}NTW`A6WOSrw&Y`3C%5ak}^FkcxDJYEZ;8|`k({4L=wN`Yi+FGom+(x>D42?OMzBNn zw8Sc-*l|sWfO#q~_=Ug-?3Cik6^J_-Vn%j5HnYrTNO^n4Hg>v(0jkb5%oIO)J&Fsc z07^qkDI5JN?hJu1_yK+S9Y1O`-e;p3%Re~+0ocB-G_tfv^8$*C%x+l=EZlSpxyaZl zs~;GcMI*OciOfCYfw6Dg&UIeIvpk-?rJqFwJ~=45Sd0(NedB{%$9x|{Iw+;0kCD^& zWN`Ufzu1d5=D!_}DX-hYW>_6l993L?kK(Wpf+EGlm3KQnbO?Pb&O`EyORmQ|Li5R5 zRZr$bzk$|5vX-1-8f9Y&X$9#?NE)L!N_bPPT0Bfel&18WJBoH*!qeNh656o}ig%8t z9UD)ESC(E^pc|?hIjpV{=w~dRd$$9crOfYX)rPu6T%dS6GK1M7UZ-BLwWHI{++aX#? z`#yJM-;IW@dBoD@^3ap=SC||0F<8~F;K3&QC?Vmhw(^Sio@s85t%?$qt#0*owkQh^ z8TOQ|t4~oN%ZiK#rurl@ALRB6yHk6{L4L3BP_L(TtfvCj({Cp0sfaqoz2aVBC$Bn5 z-J-7hVLz$6t?RO#!Mgjf|9-Ah8NDZK5$jnfBU^iF9$;aUD*KRr!^r70y|{R17t)F1 zDAd=Oyv&4y!JaB}IJ(f{JT&}zX(OcaK7@PDuS`mWjO>&-tho}_+!X$mpp59;oH=V0 zjQ*)ZxO{qAE3K~Gx>0-cbI44QEPjh%aLdgZ{nLj#dp6?wCK~;a&1b|lqj+zGxbnEM z#7eIr8D02T^v4nl1D3s57)ptSVJxvQSc!#U+?~R2XKNZ%v@W76 z1y4n3U7I&9xBMN?-t;=S83ih=+HGf7BwO|w_EcAqRyPyFLfSV`piK>YrpJBH2lP(s zp0i82ma1qn7CTV>rmyuw0*L`9Fv&QSx9KPs06~4-u-DgV9%zJK2Z9(>kM(uD4kN=Z zpG5Z;BB)fI2BdK)6Mo-okV&tvOGDcF5O%$$zu{AwmbR)hLXCAT`_5lLa=DBY6WA%X<=G`mbL?&B|{KvhIB-A4pW^1zF=S1DmxU!0D46a zov=z=(r>OcNum7XZzh{)O$;(g4)zPkC#hs&!g?Vz7sgYg@Ky7AoA_&JMv>SLZwln0 zKf{%XC?%tRY+0Hb$R@H*QH8%FVm}o^*F1obv~51rY9V&B!uLMf|NdvjUNs+=v~nL8 zwgbPT2tz6|QOY_D3gzenTGJ_@p%nLQs#q#(^`wRX2mGU^SvV@M* z>r9>m7A5;kg);2q9h_@_wrjQs+c!Y9iWPEDu70_bghX&q) zQgG<4!d`Kwq<)+1>p95!5Cbi@crXr&Sm^-b<#rB}XYQGw<{su@ho?3$R?CzI&N}(e zDu=>p^U=Wf%lj0Ljo&vvgx)cjNGPV}!d3Musts-`a-Yx2ueyFSq89bqKV?&Fx0LIj zPq3LtGYhY_0+`Ce*A@oVGf;?4V)i)SKZ`^_nfnb0xcdS>>=VG=5Kyq|%^kHVfB>%H z{dkglh37V!Lh`YdZbp!h*ohv4FwbQa{|uLg+Z=(3geWl4&L}X=4q&1nJ_M08nRKt- zKz+4>1aKC?CtzJ4NJ;GRU*Sr6?7x_5%o^B58`NxHMj<6|+^F`=D|U54Xj)yz%W+X` z33};|}F^q1UHIFc<1!CCWQnmq{0q;}zB_#{_0`5$irqQ1orHKsJlx|6i#Ehs8+<+q4ejX%N zsan6HU%q_lqy0ZLLTI2X9odU~z|rYmOoVScYS`s@X5W`ivg zoG=k}m=8J|{$@`kj4SpX7<*I0HN}Y_IUB(i(T3UYawq7_^BAj7VZphF#;W#>)tmOW zzj^g*2pvKU zQIe^Uu>KL+^$fEMAX1pi+YoH7K&*k$3`SEC41l`O`>+SI41_st4b`^gL+uX`FM?+# z=s+!!zF@9|oCqOHckMZ_hUzA+V3r|GL61+n2HW%%q|>AeXzG2 z>z6KkFn^&vf5E*(91oS(E_`S4!rxfDu*wHddf6VTtVu?3rnu=0yqxGR}Ms^r(NB@OgC)?Rfx*(oS zs#AX*ZH@>}>^ueJaWdV18v_ zsHLT`hejfaL7<*b89#yJ?vSj=&yfI%N~od+7@mr`i#QB37h6AsBjMqHiH3w*<;)6D zLe5QY-Ji}7lOS+}S081KQr{&^oQ9*VP{N66$2y91H819Q?NhO08NS%$AIpjf&A&?r zXB`(-oQEmCWK9aBO+3r~NMTF3LL14b)xd=r{t{0O;xTv@3sf=7mHW|6l zM6qkpD)nGs>Ajj*lrj=|m>gV>SZ~c*|GAI$(}Ts-3nA$Z$Ju#gWjPE;;pxq^@ah>X z28)YfZg^BrZyCzpsI5I|-Y19V{lrK&&t?kW1w)Z8TxI%<-q(B z*o#=q4$Ka86j%Ui)M56kc0OpF$gXL-F0ncWI1q!EprZdu!h|-vvlBearh)A z&bR#z66bzg6!=ntUc-CpT_*1_8QtzhNR^w8q?yn*S`=!b zbq~)$xo8@PPh6eCdGtIErd1ABm+%zFK?B|{qK9bgGz%P_cCvsMIPKp?CTC1z+UN9T zLKhW%vNh{U*xr!(xOjEprVjId~3 zQoP^9mHiQlC0tL-1gBP7fiuJgiyJJDtomOO6TCPeu#^c(U(~U>FhJ571&5i~DtIRQ zg*oEQ6iXBj$q^w3og5wH({sh*%G)<-pI}O|ByEdg8rZ3juS$$&%_&5wxP)0`ShG|Bc+3cGaesI-2dl| zdT;r^f;Vz~{z`e{4k!MZc;oC4seB>sIMl!w;g3J%2*{bhA4kddSH~giX#IQa=MabF z{gLgGa4g|^S`ImREeKjedg2`v;h;FeA}NY4v(2}VWWEctFn)`^2>${c67fvNHE`5( zkuG@1=aGMfo?#IG@@^641(?ZGu}>^eCAihVfdvPUu@S|_*W&!H7skf!8g3WmOfxn% zV&iITc7oXGtQ@6jCh$Ta`xbzU3oOeC!xzyv|Bx7_3`GY8oC@F{~2p2KzmXx zWKtES9he?-ExNg!j|_F5j$=_C&M)UdI5;n)BgJe8)(b?;xD{A2Cd7SoDlRZS$N67SX0ChCt6`3? zoncdkSO(~=0`C!+q2cDCy`z!62Y*mV+KE|$HN@}$bA;220=oD!1cK%SoLAB-rKv3t zU>6b|5_vdPu-)Juj((gCdT&!j7UP9-0;1q+vB6dVTIG|A!r?Ff^^OMBU@E}H7qai3zK(v#bj`>Zv z(CZMe1bJ&f@_GxAS@3#kIhzu#qXJlowDCw!b>c}x#~qDczl~FKAE?5F0|zV&yf~oUQp2o%tPdXLnjF^3M0BGCF6ttJ-n~ry`0n) z+lNG{$jnK5;?l%W4h(F|qoWnNL);eHNe<442N^C9(1xcM8pG7!yi5l;CE#h`2GdI; zh;ui9WuyrdNK6`6f`G4E*8nr9EIV*pjT{}mCc#(Bv??+p=1PLJVZ&ZBM0j+ylO+ji z8yxP@DF8-5z=#EnrLY;KX2;OO!5`*agOb>ALioZ1oh_Uj$`od#Ku?brjw_M~4gp_K z26VN9yW9d0!Nb9FbgAQoP4^GJB>PBm_zCnScmq);yAK@0df1?VQtmO>=Oq(Es|AD;UH;cO$_3<8KB$t=+Iy<-|@o&76pi#*V4ZQjBzA zdEKT^`4V}A#C8;GpBeKjv2kw=M}Gno0Zoqq#UphTz<36nBxv3B8XRSV8_jR|m;(0tmJeT090@2+f|^7^>pR#vRE1VA+=|C;+>}s( zcUhh2g|Bq<;#{euK0u_&i;tkC0yYvNQQ+tudodf z4u?(YF_e`YLk$EuEY4~rF1!QioWG6jX$`w7LDhae*bs*fpSa^LLcR;b#dRWNU00$< z4tNV%3+da6J5D?bkMvInL5lDi1yTX&nvl37ssVP6`X^8GPA;cK*D}s0+F{Af* z#Fn;2fyDI{;)VmrPnqbF$UB3;(Imbap`+g%gpRIbOu;?40fbxY_B{w45?-3Tn|J_w z_u)(irxq}yB)X9L^N{d20)USF2Ah-DD0v7%a1=KDCsDgv9z|8KNRc>zk{dk3!|dTd z7q)^E5XR;TuhnwRa5Kmgoe-nJxgpL%M3C2{Z-I~pe2`Ci3g|-IJH4|o$f2Oqq2@x) z437ZA9lwhsK+PHxEU=$Ou;c75j>wD&dj_~r90COLGBR8SHu5$m=*X7`6ZfPRxb@Lh zUFJbgfFm*sZ|Z>&X$b`#0-n3)BQK{npZv1sWn5jl_hf=HGSJ6cvibmmc92R~nikB5 zkUYrVfios#5z?`y1cI+!;)4$S-&`)fHTEU(t4EQMZcI*`{pb>x2SDvXWTP`#xZ6hb zs-A8Tk_>`Tt2YM0^aEg$Tqfjt_q%KZZgM_kz4Fd3Bh)cigp0!qAdTf+!*Zj89JaL1CaE2(m5rzR+v6~kX&k9? zK?HlM?MH~S7y*D&C*QGH#6FhAucJc=ve3JwU^&}f#QP0EJf?4&ArZHMZIr`i^D>u! zJqg_hC`q{YKooxzn`z)O11uzpUK2_xS9|#K0#>yI4PhI63@kkz!8fYZ$`;Dl1xn7? znHj2p*bj;CMx&2uN~>a)54zZ@F|1uv~^gjCU^LiK$#Z4_ykZctYuWyi;*0e_Jlw8W$;i48jxl zF5$lMc(&ox$FHYMLp=a+>bH+s7Un>QC`@8OGHk-$6Um;h&@SOj7&LrFP-5wP$|<-*!NJoW|YlxrZi3 z1%(bh6d(J}3A}SXd*`IQ15DtZ(&OGq$BQ75s`-~dYi?fML)t$D+b_NDwe&%0MV8J& ze>Q!9O-{=P3xmpXFI$BR{nJC0*+#m;9(|IoxP|H|y>Mia$a47@@W?8bb=e{%;j1o@ z6RE$&C$iRlkGX+ld{cqyx~xcj`}&PrvNWNoi}Q0_xZSw< zU0JAc;TE#+T{%j-A)VL9@EHN}s@Mb{Ikb+cKDV*%0~`L$V)^fK6n5xJo)OA<(8rNOvJ@ChBP{-0KpnKY|2(Mw>YRLnnQu!ASyWB zF63HBGuV+Ke;}thsV2l!91&qlyY7h*5;iYkjls9pF^mmzpN>3m?00tYT@VaPLQ(Nq7zCM$nO9HBsLCaHTEr~LmtQcK8gWO7V345& zHM(7mJ&k{mhWzoD*D@~g&Bx&w1M>`q5 zy1zFFf`fa0B{44O&!Cw)&dkI|E=CtT;^86X#M%&HC#{HXIS&+e9ioReQdkAX6k-9?HpJwTSS}S3lZ+ z?K8v9S|E0K(N3vD9RxT0hQ@nX{~wyE@zW5|2S8s#P4&l24&h|{RR$a1@2b}xrl1#c z{c{?0u@MZy1JjzR8{O+{?*PeT+~_Xg(ce#7&6)l3pw(~sVQ0f1cWPY3`lZaHI?yfojR908*S$=t@%!~9WrVU-U^Qu^C9kL8L#LzUlQN2Dfx z?#Iek3YCK5{VZ6BxF#UWxWfO0#AQ4yRv|>~MaG5TyLF2s68T`oLS#f{gm{q$CSrbb z9ZT}ax%qvQL?pG|Cb5u2>u}Ev9JdA1!?Ix;b zZLR;U*P+Ve6I$BX0B#C?iz7MxJ&lO3x=_B8Z>yhr3aAp*p8Em0tk)bSv*_?S-=> z-(%7$%vBb-VAZcPxy59Y$rclFD*XUCe!(N`-4Xk0JoP%hX@H}-prZ}qORV}2nY@Gq z%Z2-3JeJ5S^~xqbJ_#W}xW}RGQT-9B{uznso5nudp@i!_wqAuCk57EP#vMLfK|;r(iUcz;plRq| re)_d(YkGRRJbill&FODUPfq{Z^f6pB_;-8yZ%&^tf2&kT{^kES`_%M* diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/utils.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/__pycache__/utils.cpython-37.pyc deleted file mode 100644 index 8afe9a61ea69a08686bee9fcd6b60ec15da3ed3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15442 zcmd5@OLH98b?)wYVgP~MU(WWSqBa?tE$(9UDv?!907}Frjq)d5CdC-{K12i${ z9^dXE2za1MnTlg4Q7Vg6rJ_y9%A?Aaq*AWzQpqNZ{DxF-v=5?vuys({htNLMIwbAGXdiAJmi7^} zkF<_R`-$EY8%JA5ZOfmDe}z39#k*szW40B(=pXqbTc5zQW4$Lgj<=3W|0mHt(K;dR z<7l63oy6E#|0(|qUFW#fdRm=OCqJ@U�%=7jS=8J*}R>{W~Xq{1C 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 cmd_param.nargs: - break - if start_of_option(arg_str): - last_option = arg_str - - return True if last_option and last_option in cmd_param.opts else False - - -def is_incomplete_argument(current_params, cmd_param): - """ - :param current_params: the current params and values for this - argument as already entered - :param cmd_param: the current command parameter - :return: whether or not the last argument is incomplete and - corresponds to this cmd_param. In other words whether or not the - this cmd_param argument can still accept values - """ - if not isinstance(cmd_param, Argument): - return False - current_param_values = current_params[cmd_param.name] - if current_param_values is None: - return True - if cmd_param.nargs == -1: - return True - if ( - isinstance(current_param_values, abc.Iterable) - and cmd_param.nargs > 1 - and len(current_param_values) < cmd_param.nargs - ): - return True - return False - - -def get_user_autocompletions(ctx, args, incomplete, cmd_param): - """ - :param ctx: context associated with the parsed command - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :param cmd_param: command definition - :return: all the possible user-specified completions for the param - """ - results = [] - if isinstance(cmd_param.type, Choice): - # Choices don't support descriptions. - results = [ - (c, None) for c in cmd_param.type.choices if str(c).startswith(incomplete) - ] - elif cmd_param.autocompletion is not None: - dynamic_completions = cmd_param.autocompletion( - ctx=ctx, args=args, incomplete=incomplete - ) - results = [ - c if isinstance(c, tuple) else (c, None) for c in dynamic_completions - ] - return results - - -def get_visible_commands_starting_with(ctx, starts_with): - """ - :param ctx: context associated with the parsed command - :starts_with: string that visible commands must start with. - :return: all visible (not hidden) commands that start with starts_with. - """ - for c in ctx.command.list_commands(ctx): - if c.startswith(starts_with): - command = ctx.command.get_command(ctx, c) - if not command.hidden: - yield command - - -def add_subcommand_completions(ctx, incomplete, completions_out): - # Add subcommand completions. - if isinstance(ctx.command, MultiCommand): - completions_out.extend( - [ - (c.name, c.get_short_help_str()) - for c in get_visible_commands_starting_with(ctx, incomplete) - ] - ) - - # Walk up the context list and add any other completion - # possibilities from chained commands - while ctx.parent is not None: - ctx = ctx.parent - if isinstance(ctx.command, MultiCommand) and ctx.command.chain: - remaining_commands = [ - c - for c in get_visible_commands_starting_with(ctx, incomplete) - if c.name not in ctx.protected_args - ] - completions_out.extend( - [(c.name, c.get_short_help_str()) for c in remaining_commands] - ) - - -def get_choices(cli, prog_name, args, incomplete): - """ - :param cli: command definition - :param prog_name: the program that is running - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :return: all the possible completions for the incomplete - """ - all_args = copy.deepcopy(args) - - ctx = resolve_ctx(cli, prog_name, args) - if ctx is None: - return [] - - has_double_dash = "--" in all_args - - # In newer versions of bash long opts with '='s are partitioned, but - # it's easier to parse without the '=' - if start_of_option(incomplete) and WORDBREAK in incomplete: - partition_incomplete = incomplete.partition(WORDBREAK) - all_args.append(partition_incomplete[0]) - incomplete = partition_incomplete[2] - elif incomplete == WORDBREAK: - incomplete = "" - - completions = [] - if not has_double_dash and start_of_option(incomplete): - # completions for partial options - for param in ctx.command.params: - if isinstance(param, Option) and not param.hidden: - param_opts = [ - param_opt - for param_opt in param.opts + param.secondary_opts - if param_opt not in all_args or param.multiple - ] - completions.extend( - [(o, param.help) for o in param_opts if o.startswith(incomplete)] - ) - return completions - # completion for option values from user supplied values - for param in ctx.command.params: - if is_incomplete_option(all_args, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - # completion for argument values from user supplied values - for param in ctx.command.params: - if is_incomplete_argument(ctx.params, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - - add_subcommand_completions(ctx, incomplete, completions) - # Sort before returning so that proper ordering can be enforced in custom types. - return sorted(completions) - - -def do_complete(cli, prog_name, include_descriptions): - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - for item in get_choices(cli, prog_name, args, incomplete): - echo(item[0]) - if include_descriptions: - # ZSH has trouble dealing with empty array parameters when - # returned from commands, use '_' to indicate no description - # is present. - echo(item[1] if item[1] else "_") - - return True - - -def do_complete_fish(cli, prog_name): - cwords = split_arg_string(os.environ["COMP_WORDS"]) - incomplete = os.environ["COMP_CWORD"] - args = cwords[1:] - - for item in get_choices(cli, prog_name, args, incomplete): - if item[1]: - echo("{arg}\t{desc}".format(arg=item[0], desc=item[1])) - else: - echo(item[0]) - - return True - - -def bashcomplete(cli, prog_name, complete_var, complete_instr): - if "_" in complete_instr: - command, shell = complete_instr.split("_", 1) - else: - command = complete_instr - shell = "bash" - - if command == "source": - echo(get_completion_script(prog_name, complete_var, shell)) - return True - elif command == "complete": - if shell == "fish": - return do_complete_fish(cli, prog_name) - elif shell in {"bash", "zsh"}: - return do_complete(cli, prog_name, shell == "zsh") - - return False diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_compat.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_compat.py deleted file mode 100644 index ed57a18..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_compat.py +++ /dev/null @@ -1,790 +0,0 @@ -# flake8: noqa -import codecs -import io -import os -import re -import sys -from weakref import WeakKeyDictionary - -PY2 = sys.version_info[0] == 2 -CYGWIN = sys.platform.startswith("cygwin") -MSYS2 = sys.platform.startswith("win") and ("GCC" in sys.version) -# Determine local App Engine environment, per Google's own suggestion -APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ.get( - "SERVER_SOFTWARE", "" -) -WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2 -DEFAULT_COLUMNS = 80 - - -_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") - - -def get_filesystem_encoding(): - return sys.getfilesystemencoding() or sys.getdefaultencoding() - - -def _make_text_stream( - stream, encoding, errors, force_readable=False, force_writable=False -): - if encoding is None: - encoding = get_best_encoding(stream) - if errors is None: - errors = "replace" - return _NonClosingTextIOWrapper( - stream, - encoding, - errors, - line_buffering=True, - force_readable=force_readable, - force_writable=force_writable, - ) - - -def is_ascii_encoding(encoding): - """Checks if a given encoding is ascii.""" - try: - return codecs.lookup(encoding).name == "ascii" - except LookupError: - return False - - -def get_best_encoding(stream): - """Returns the default stream encoding if not found.""" - rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() - if is_ascii_encoding(rv): - return "utf-8" - return rv - - -class _NonClosingTextIOWrapper(io.TextIOWrapper): - def __init__( - self, - stream, - encoding, - errors, - force_readable=False, - force_writable=False, - **extra - ): - self._stream = stream = _FixupStream(stream, force_readable, force_writable) - io.TextIOWrapper.__init__(self, stream, encoding, errors, **extra) - - # The io module is a place where the Python 3 text behavior - # was forced upon Python 2, so we need to unbreak - # it to look like Python 2. - if PY2: - - def write(self, x): - if isinstance(x, str) or is_bytes(x): - try: - self.flush() - except Exception: - pass - return self.buffer.write(str(x)) - return io.TextIOWrapper.write(self, x) - - def writelines(self, lines): - for line in lines: - self.write(line) - - def __del__(self): - try: - self.detach() - except Exception: - pass - - def isatty(self): - # https://bitbucket.org/pypy/pypy/issue/1803 - return self._stream.isatty() - - -class _FixupStream(object): - """The new io interface needs more from streams than streams - traditionally implement. As such, this fix-up code is necessary in - some circumstances. - - The forcing of readable and writable flags are there because some tools - put badly patched objects on sys (one such offender are certain version - of jupyter notebook). - """ - - def __init__(self, stream, force_readable=False, force_writable=False): - self._stream = stream - self._force_readable = force_readable - self._force_writable = force_writable - - def __getattr__(self, name): - return getattr(self._stream, name) - - def read1(self, size): - f = getattr(self._stream, "read1", None) - if f is not None: - return f(size) - # We only dispatch to readline instead of read in Python 2 as we - # do not want cause problems with the different implementation - # of line buffering. - if PY2: - return self._stream.readline(size) - return self._stream.read(size) - - def readable(self): - if self._force_readable: - return True - x = getattr(self._stream, "readable", None) - if x is not None: - return x() - try: - self._stream.read(0) - except Exception: - return False - return True - - def writable(self): - if self._force_writable: - return True - x = getattr(self._stream, "writable", None) - if x is not None: - return x() - try: - self._stream.write("") - except Exception: - try: - self._stream.write(b"") - except Exception: - return False - return True - - def seekable(self): - x = getattr(self._stream, "seekable", None) - if x is not None: - return x() - try: - self._stream.seek(self._stream.tell()) - except Exception: - return False - return True - - -if PY2: - text_type = unicode - raw_input = raw_input - string_types = (str, unicode) - int_types = (int, long) - iteritems = lambda x: x.iteritems() - range_type = xrange - - from pipes import quote as shlex_quote - - def is_bytes(x): - return isinstance(x, (buffer, bytearray)) - - _identifier_re = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$") - - # For Windows, we need to force stdout/stdin/stderr to binary if it's - # fetched for that. This obviously is not the most correct way to do - # it as it changes global state. Unfortunately, there does not seem to - # be a clear better way to do it as just reopening the file in binary - # mode does not change anything. - # - # An option would be to do what Python 3 does and to open the file as - # binary only, patch it back to the system, and then use a wrapper - # stream that converts newlines. It's not quite clear what's the - # correct option here. - # - # This code also lives in _winconsole for the fallback to the console - # emulation stream. - # - # There are also Windows environments where the `msvcrt` module is not - # available (which is why we use try-catch instead of the WIN variable - # here), such as the Google App Engine development server on Windows. In - # those cases there is just nothing we can do. - def set_binary_mode(f): - return f - - try: - import msvcrt - except ImportError: - pass - else: - - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - msvcrt.setmode(fileno, os.O_BINARY) - return f - - try: - import fcntl - except ImportError: - pass - else: - - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - flags = fcntl.fcntl(fileno, fcntl.F_GETFL) - fcntl.fcntl(fileno, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) - return f - - def isidentifier(x): - return _identifier_re.search(x) is not None - - def get_binary_stdin(): - return set_binary_mode(sys.stdin) - - def get_binary_stdout(): - _wrap_std_stream("stdout") - return set_binary_mode(sys.stdout) - - def get_binary_stderr(): - _wrap_std_stream("stderr") - return set_binary_mode(sys.stderr) - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdin, encoding, errors, force_readable=True) - - def get_text_stdout(encoding=None, errors=None): - _wrap_std_stream("stdout") - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdout, encoding, errors, force_writable=True) - - def get_text_stderr(encoding=None, errors=None): - _wrap_std_stream("stderr") - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stderr, encoding, errors, force_writable=True) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), "replace") - return value - - -else: - import io - - text_type = str - raw_input = input - string_types = (str,) - int_types = (int,) - range_type = range - isidentifier = lambda x: x.isidentifier() - iteritems = lambda x: iter(x.items()) - - from shlex import quote as shlex_quote - - def is_bytes(x): - return isinstance(x, (bytes, memoryview, bytearray)) - - def _is_binary_reader(stream, default=False): - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - def _is_binary_writer(stream, default=False): - try: - stream.write(b"") - except Exception: - try: - stream.write("") - return False - except Exception: - pass - return default - return True - - def _find_binary_reader(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_reader(stream, False): - return stream - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_reader(buf, True): - return buf - - def _find_binary_writer(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detatching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_writer(stream, False): - return stream - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_writer(buf, True): - return buf - - def _stream_is_misconfigured(stream): - """A stream is misconfigured if its encoding is ASCII.""" - # If the stream does not have an encoding set, we assume it's set - # to ASCII. This appears to happen in certain unittest - # environments. It's not quite clear what the correct behavior is - # but this at least will force Click to recover somehow. - return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") - - def _is_compat_stream_attr(stream, attr, value): - """A stream attribute is compatible if it is equal to the - desired value or the desired value is unset and the attribute - has a value. - """ - stream_value = getattr(stream, attr, None) - return stream_value == value or (value is None and stream_value is not None) - - def _is_compatible_text_stream(stream, encoding, errors): - """Check if a stream's encoding and errors attributes are - compatible with the desired values. - """ - return _is_compat_stream_attr( - stream, "encoding", encoding - ) and _is_compat_stream_attr(stream, "errors", errors) - - def _force_correct_text_stream( - text_stream, - encoding, - errors, - is_binary, - find_binary, - force_readable=False, - force_writable=False, - ): - if is_binary(text_stream, False): - binary_reader = text_stream - else: - # If the stream looks compatible, and won't default to a - # misconfigured ascii encoding, return it as-is. - if _is_compatible_text_stream(text_stream, encoding, errors) and not ( - encoding is None and _stream_is_misconfigured(text_stream) - ): - return text_stream - - # Otherwise, get the underlying binary reader. - binary_reader = find_binary(text_stream) - - # If that's not possible, silently use the original reader - # and get mojibake instead of exceptions. - if binary_reader is None: - return text_stream - - # Default errors to replace instead of strict in order to get - # something that works. - if errors is None: - errors = "replace" - - # Wrap the binary stream in a text stream with the correct - # encoding parameters. - return _make_text_stream( - binary_reader, - encoding, - errors, - force_readable=force_readable, - force_writable=force_writable, - ) - - def _force_correct_text_reader(text_reader, encoding, errors, force_readable=False): - return _force_correct_text_stream( - text_reader, - encoding, - errors, - _is_binary_reader, - _find_binary_reader, - force_readable=force_readable, - ) - - def _force_correct_text_writer(text_writer, encoding, errors, force_writable=False): - return _force_correct_text_stream( - text_writer, - encoding, - errors, - _is_binary_writer, - _find_binary_writer, - force_writable=force_writable, - ) - - def get_binary_stdin(): - reader = _find_binary_reader(sys.stdin) - if reader is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdin.") - return reader - - def get_binary_stdout(): - writer = _find_binary_writer(sys.stdout) - if writer is None: - raise RuntimeError( - "Was not able to determine binary stream for sys.stdout." - ) - return writer - - def get_binary_stderr(): - writer = _find_binary_writer(sys.stderr) - if writer is None: - raise RuntimeError( - "Was not able to determine binary stream for sys.stderr." - ) - return writer - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_reader( - sys.stdin, encoding, errors, force_readable=True - ) - - def get_text_stdout(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer( - sys.stdout, encoding, errors, force_writable=True - ) - - def get_text_stderr(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer( - sys.stderr, encoding, errors, force_writable=True - ) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), "replace") - else: - value = value.encode("utf-8", "surrogateescape").decode("utf-8", "replace") - return value - - -def get_streerror(e, default=None): - if hasattr(e, "strerror"): - msg = e.strerror - else: - if default is not None: - msg = default - else: - msg = str(e) - if isinstance(msg, bytes): - msg = msg.decode("utf-8", "replace") - return msg - - -def _wrap_io_open(file, mode, encoding, errors): - """On Python 2, :func:`io.open` returns a text file wrapper that - requires passing ``unicode`` to ``write``. Need to open the file in - binary mode then wrap it in a subclass that can write ``str`` and - ``unicode``. - - Also handles not passing ``encoding`` and ``errors`` in binary mode. - """ - binary = "b" in mode - - if binary: - kwargs = {} - else: - kwargs = {"encoding": encoding, "errors": errors} - - if not PY2 or binary: - return io.open(file, mode, **kwargs) - - f = io.open(file, "{}b".format(mode.replace("t", ""))) - return _make_text_stream(f, **kwargs) - - -def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False): - binary = "b" in mode - - # Standard streams first. These are simple because they don't need - # special handling for the atomic flag. It's entirely ignored. - if filename == "-": - if any(m in mode for m in ["w", "a", "x"]): - if binary: - return get_binary_stdout(), False - return get_text_stdout(encoding=encoding, errors=errors), False - if binary: - return get_binary_stdin(), False - return get_text_stdin(encoding=encoding, errors=errors), False - - # Non-atomic writes directly go out through the regular open functions. - if not atomic: - return _wrap_io_open(filename, mode, encoding, errors), True - - # Some usability stuff for atomic writes - if "a" in mode: - raise ValueError( - "Appending to an existing file is not supported, because that" - " would involve an expensive `copy`-operation to a temporary" - " file. Open the file in normal `w`-mode and copy explicitly" - " if that's what you're after." - ) - if "x" in mode: - raise ValueError("Use the `overwrite`-parameter instead.") - if "w" not in mode: - raise ValueError("Atomic writes only make sense with `w`-mode.") - - # Atomic writes are more complicated. They work by opening a file - # as a proxy in the same folder and then using the fdopen - # functionality to wrap it in a Python file. Then we wrap it in an - # atomic file that moves the file over on close. - import errno - import random - - try: - perm = os.stat(filename).st_mode - except OSError: - perm = None - - flags = os.O_RDWR | os.O_CREAT | os.O_EXCL - - if binary: - flags |= getattr(os, "O_BINARY", 0) - - while True: - tmp_filename = os.path.join( - os.path.dirname(filename), - ".__atomic-write{:08x}".format(random.randrange(1 << 32)), - ) - try: - fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) - break - except OSError as e: - if e.errno == errno.EEXIST or ( - os.name == "nt" - and e.errno == errno.EACCES - and os.path.isdir(e.filename) - and os.access(e.filename, os.W_OK) - ): - continue - raise - - if perm is not None: - os.chmod(tmp_filename, perm) # in case perm includes bits in umask - - f = _wrap_io_open(fd, mode, encoding, errors) - return _AtomicFile(f, tmp_filename, os.path.realpath(filename)), True - - -# Used in a destructor call, needs extra protection from interpreter cleanup. -if hasattr(os, "replace"): - _replace = os.replace - _can_replace = True -else: - _replace = os.rename - _can_replace = not WIN - - -class _AtomicFile(object): - def __init__(self, f, tmp_filename, real_filename): - self._f = f - self._tmp_filename = tmp_filename - self._real_filename = real_filename - self.closed = False - - @property - def name(self): - return self._real_filename - - def close(self, delete=False): - if self.closed: - return - self._f.close() - if not _can_replace: - try: - os.remove(self._real_filename) - except OSError: - pass - _replace(self._tmp_filename, self._real_filename) - self.closed = True - - def __getattr__(self, name): - return getattr(self._f, name) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close(delete=exc_type is not None) - - def __repr__(self): - return repr(self._f) - - -auto_wrap_for_ansi = None -colorama = None -get_winterm_size = None - - -def strip_ansi(value): - return _ansi_re.sub("", value) - - -def _is_jupyter_kernel_output(stream): - if WIN: - # TODO: Couldn't test on Windows, should't try to support until - # someone tests the details wrt colorama. - return - - while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): - stream = stream._stream - - return stream.__class__.__module__.startswith("ipykernel.") - - -def should_strip_ansi(stream=None, color=None): - if color is None: - if stream is None: - stream = sys.stdin - return not isatty(stream) and not _is_jupyter_kernel_output(stream) - return not color - - -# If we're on Windows, we provide transparent integration through -# colorama. This will make ANSI colors through the echo function -# work automatically. -if WIN: - # Windows has a smaller terminal - DEFAULT_COLUMNS = 79 - - from ._winconsole import _get_windows_console_stream, _wrap_std_stream - - def _get_argv_encoding(): - import locale - - return locale.getpreferredencoding() - - if PY2: - - def raw_input(prompt=""): - sys.stderr.flush() - if prompt: - stdout = _default_text_stdout() - stdout.write(prompt) - stdin = _default_text_stdin() - return stdin.readline().rstrip("\r\n") - - try: - import colorama - except ImportError: - pass - else: - _ansi_stream_wrappers = WeakKeyDictionary() - - def auto_wrap_for_ansi(stream, color=None): - """This function wraps a stream so that calls through colorama - are issued to the win32 console API to recolor on demand. It - also ensures to reset the colors if a write call is interrupted - to not destroy the console afterwards. - """ - try: - cached = _ansi_stream_wrappers.get(stream) - except Exception: - cached = None - if cached is not None: - return cached - strip = should_strip_ansi(stream, color) - ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) - rv = ansi_wrapper.stream - _write = rv.write - - def _safe_write(s): - try: - return _write(s) - except: - ansi_wrapper.reset_all() - raise - - rv.write = _safe_write - try: - _ansi_stream_wrappers[stream] = rv - except Exception: - pass - return rv - - def get_winterm_size(): - win = colorama.win32.GetConsoleScreenBufferInfo( - colorama.win32.STDOUT - ).srWindow - return win.Right - win.Left, win.Bottom - win.Top - - -else: - - def _get_argv_encoding(): - return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding() - - _get_windows_console_stream = lambda *x: None - _wrap_std_stream = lambda *x: None - - -def term_len(x): - return len(strip_ansi(x)) - - -def isatty(stream): - try: - return stream.isatty() - except Exception: - return False - - -def _make_cached_stream_func(src_func, wrapper_func): - cache = WeakKeyDictionary() - - def func(): - stream = src_func() - try: - rv = cache.get(stream) - except Exception: - rv = None - if rv is not None: - return rv - rv = wrapper_func() - try: - stream = src_func() # In case wrapper_func() modified the stream - cache[stream] = rv - except Exception: - pass - return rv - - return func - - -_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) -_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) -_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) - - -binary_streams = { - "stdin": get_binary_stdin, - "stdout": get_binary_stdout, - "stderr": get_binary_stderr, -} - -text_streams = { - "stdin": get_text_stdin, - "stdout": get_text_stdout, - "stderr": get_text_stderr, -} diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_termui_impl.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_termui_impl.py deleted file mode 100644 index c6e86cc..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_termui_impl.py +++ /dev/null @@ -1,661 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module contains implementations for the termui module. To keep the -import time of Click down, some infrequently used functionality is -placed in this module and only imported as needed. -""" -import contextlib -import math -import os -import sys -import time - -from ._compat import _default_text_stdout -from ._compat import CYGWIN -from ._compat import get_best_encoding -from ._compat import int_types -from ._compat import isatty -from ._compat import open_stream -from ._compat import range_type -from ._compat import shlex_quote -from ._compat import strip_ansi -from ._compat import term_len -from ._compat import WIN -from .exceptions import ClickException -from .utils import echo - -if os.name == "nt": - BEFORE_BAR = "\r" - AFTER_BAR = "\n" -else: - BEFORE_BAR = "\r\033[?25l" - AFTER_BAR = "\033[?25h\n" - - -def _length_hint(obj): - """Returns the length hint of an object.""" - try: - return len(obj) - except (AttributeError, TypeError): - try: - get_hint = type(obj).__length_hint__ - except AttributeError: - return None - try: - hint = get_hint(obj) - except TypeError: - return None - if hint is NotImplemented or not isinstance(hint, int_types) or hint < 0: - return None - return hint - - -class ProgressBar(object): - def __init__( - self, - iterable, - length=None, - fill_char="#", - empty_char=" ", - bar_template="%(bar)s", - info_sep=" ", - show_eta=True, - show_percent=None, - show_pos=False, - item_show_func=None, - label=None, - file=None, - color=None, - width=30, - ): - self.fill_char = fill_char - self.empty_char = empty_char - self.bar_template = bar_template - self.info_sep = info_sep - self.show_eta = show_eta - self.show_percent = show_percent - self.show_pos = show_pos - self.item_show_func = item_show_func - self.label = label or "" - if file is None: - file = _default_text_stdout() - self.file = file - self.color = color - self.width = width - self.autowidth = width == 0 - - if length is None: - length = _length_hint(iterable) - if iterable is None: - if length is None: - raise TypeError("iterable or length is required") - iterable = range_type(length) - self.iter = iter(iterable) - self.length = length - self.length_known = length is not None - self.pos = 0 - self.avg = [] - self.start = self.last_eta = time.time() - self.eta_known = False - self.finished = False - self.max_width = None - self.entered = False - self.current_item = None - self.is_hidden = not isatty(self.file) - self._last_line = None - self.short_limit = 0.5 - - def __enter__(self): - self.entered = True - self.render_progress() - return self - - def __exit__(self, exc_type, exc_value, tb): - self.render_finish() - - def __iter__(self): - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - self.render_progress() - return self.generator() - - def __next__(self): - # Iteration is defined in terms of a generator function, - # returned by iter(self); use that to define next(). This works - # because `self.iter` is an iterable consumed by that generator, - # so it is re-entry safe. Calling `next(self.generator())` - # twice works and does "what you want". - return next(iter(self)) - - # Python 2 compat - next = __next__ - - def is_fast(self): - return time.time() - self.start <= self.short_limit - - def render_finish(self): - if self.is_hidden or self.is_fast(): - return - self.file.write(AFTER_BAR) - self.file.flush() - - @property - def pct(self): - if self.finished: - return 1.0 - return min(self.pos / (float(self.length) or 1), 1.0) - - @property - def time_per_iteration(self): - if not self.avg: - return 0.0 - return sum(self.avg) / float(len(self.avg)) - - @property - def eta(self): - if self.length_known and not self.finished: - return self.time_per_iteration * (self.length - self.pos) - return 0.0 - - def format_eta(self): - if self.eta_known: - t = int(self.eta) - seconds = t % 60 - t //= 60 - minutes = t % 60 - t //= 60 - hours = t % 24 - t //= 24 - if t > 0: - return "{}d {:02}:{:02}:{:02}".format(t, hours, minutes, seconds) - else: - return "{:02}:{:02}:{:02}".format(hours, minutes, seconds) - return "" - - def format_pos(self): - pos = str(self.pos) - if self.length_known: - pos += "/{}".format(self.length) - return pos - - def format_pct(self): - return "{: 4}%".format(int(self.pct * 100))[1:] - - def format_bar(self): - if self.length_known: - bar_length = int(self.pct * self.width) - bar = self.fill_char * bar_length - bar += self.empty_char * (self.width - bar_length) - elif self.finished: - bar = self.fill_char * self.width - else: - bar = list(self.empty_char * (self.width or 1)) - if self.time_per_iteration != 0: - bar[ - int( - (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) - * self.width - ) - ] = self.fill_char - bar = "".join(bar) - return bar - - def format_progress_line(self): - show_percent = self.show_percent - - info_bits = [] - if self.length_known and show_percent is None: - show_percent = not self.show_pos - - if self.show_pos: - info_bits.append(self.format_pos()) - if show_percent: - info_bits.append(self.format_pct()) - if self.show_eta and self.eta_known and not self.finished: - info_bits.append(self.format_eta()) - if self.item_show_func is not None: - item_info = self.item_show_func(self.current_item) - if item_info is not None: - info_bits.append(item_info) - - return ( - self.bar_template - % { - "label": self.label, - "bar": self.format_bar(), - "info": self.info_sep.join(info_bits), - } - ).rstrip() - - def render_progress(self): - from .termui import get_terminal_size - - if self.is_hidden: - return - - buf = [] - # Update width in case the terminal has been resized - if self.autowidth: - old_width = self.width - self.width = 0 - clutter_length = term_len(self.format_progress_line()) - new_width = max(0, get_terminal_size()[0] - clutter_length) - if new_width < old_width: - buf.append(BEFORE_BAR) - buf.append(" " * self.max_width) - self.max_width = new_width - self.width = new_width - - clear_width = self.width - if self.max_width is not None: - clear_width = self.max_width - - buf.append(BEFORE_BAR) - line = self.format_progress_line() - line_len = term_len(line) - if self.max_width is None or self.max_width < line_len: - self.max_width = line_len - - buf.append(line) - buf.append(" " * (clear_width - line_len)) - line = "".join(buf) - # Render the line only if it changed. - - if line != self._last_line and not self.is_fast(): - self._last_line = line - echo(line, file=self.file, color=self.color, nl=False) - self.file.flush() - - def make_step(self, n_steps): - self.pos += n_steps - if self.length_known and self.pos >= self.length: - self.finished = True - - if (time.time() - self.last_eta) < 1.0: - return - - self.last_eta = time.time() - - # self.avg is a rolling list of length <= 7 of steps where steps are - # defined as time elapsed divided by the total progress through - # self.length. - if self.pos: - step = (time.time() - self.start) / self.pos - else: - step = time.time() - self.start - - self.avg = self.avg[-6:] + [step] - - self.eta_known = self.length_known - - def update(self, n_steps): - self.make_step(n_steps) - self.render_progress() - - def finish(self): - self.eta_known = 0 - self.current_item = None - self.finished = True - - def generator(self): - """Return a generator which yields the items added to the bar - during construction, and updates the progress bar *after* the - yielded block returns. - """ - # WARNING: the iterator interface for `ProgressBar` relies on - # this and only works because this is a simple generator which - # doesn't create or manage additional state. If this function - # changes, the impact should be evaluated both against - # `iter(bar)` and `next(bar)`. `next()` in particular may call - # `self.generator()` repeatedly, and this must remain safe in - # order for that interface to work. - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - - if self.is_hidden: - for rv in self.iter: - yield rv - else: - for rv in self.iter: - self.current_item = rv - yield rv - self.update(1) - self.finish() - self.render_progress() - - -def pager(generator, color=None): - """Decide what method to use for paging through text.""" - stdout = _default_text_stdout() - if not isatty(sys.stdin) or not isatty(stdout): - return _nullpager(stdout, generator, color) - pager_cmd = (os.environ.get("PAGER", None) or "").strip() - if pager_cmd: - if WIN: - return _tempfilepager(generator, pager_cmd, color) - return _pipepager(generator, pager_cmd, color) - if os.environ.get("TERM") in ("dumb", "emacs"): - return _nullpager(stdout, generator, color) - if WIN or sys.platform.startswith("os2"): - return _tempfilepager(generator, "more <", color) - if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: - return _pipepager(generator, "less", color) - - import tempfile - - fd, filename = tempfile.mkstemp() - os.close(fd) - try: - if ( - hasattr(os, "system") - and os.system("more {}".format(shlex_quote(filename))) == 0 - ): - return _pipepager(generator, "more", color) - return _nullpager(stdout, generator, color) - finally: - os.unlink(filename) - - -def _pipepager(generator, cmd, color): - """Page through text by feeding it to another program. Invoking a - pager through this might support colors. - """ - import subprocess - - env = dict(os.environ) - - # If we're piping to less we might support colors under the - # condition that - cmd_detail = cmd.rsplit("/", 1)[-1].split() - if color is None and cmd_detail[0] == "less": - less_flags = "{}{}".format(os.environ.get("LESS", ""), " ".join(cmd_detail[1:])) - if not less_flags: - env["LESS"] = "-R" - color = True - elif "r" in less_flags or "R" in less_flags: - color = True - - c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) - encoding = get_best_encoding(c.stdin) - try: - for text in generator: - if not color: - text = strip_ansi(text) - - c.stdin.write(text.encode(encoding, "replace")) - except (IOError, KeyboardInterrupt): - pass - else: - c.stdin.close() - - # Less doesn't respect ^C, but catches it for its own UI purposes (aborting - # search or other commands inside less). - # - # That means when the user hits ^C, the parent process (click) terminates, - # but less is still alive, paging the output and messing up the terminal. - # - # If the user wants to make the pager exit on ^C, they should set - # `LESS='-K'`. It's not our decision to make. - while True: - try: - c.wait() - except KeyboardInterrupt: - pass - else: - break - - -def _tempfilepager(generator, cmd, color): - """Page through text by invoking a program on a temporary file.""" - import tempfile - - filename = tempfile.mktemp() - # TODO: This never terminates if the passed generator never terminates. - text = "".join(generator) - if not color: - text = strip_ansi(text) - encoding = get_best_encoding(sys.stdout) - with open_stream(filename, "wb")[0] as f: - f.write(text.encode(encoding)) - try: - os.system("{} {}".format(shlex_quote(cmd), shlex_quote(filename))) - finally: - os.unlink(filename) - - -def _nullpager(stream, generator, color): - """Simply print unformatted text. This is the ultimate fallback.""" - for text in generator: - if not color: - text = strip_ansi(text) - stream.write(text) - - -class Editor(object): - def __init__(self, editor=None, env=None, require_save=True, extension=".txt"): - self.editor = editor - self.env = env - self.require_save = require_save - self.extension = extension - - def get_editor(self): - if self.editor is not None: - return self.editor - for key in "VISUAL", "EDITOR": - rv = os.environ.get(key) - if rv: - return rv - if WIN: - return "notepad" - for editor in "sensible-editor", "vim", "nano": - if os.system("which {} >/dev/null 2>&1".format(editor)) == 0: - return editor - return "vi" - - def edit_file(self, filename): - import subprocess - - editor = self.get_editor() - if self.env: - environ = os.environ.copy() - environ.update(self.env) - else: - environ = None - try: - c = subprocess.Popen( - "{} {}".format(shlex_quote(editor), shlex_quote(filename)), - env=environ, - shell=True, - ) - exit_code = c.wait() - if exit_code != 0: - raise ClickException("{}: Editing failed!".format(editor)) - except OSError as e: - raise ClickException("{}: Editing failed: {}".format(editor, e)) - - def edit(self, text): - import tempfile - - text = text or "" - if text and not text.endswith("\n"): - text += "\n" - - fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) - try: - if WIN: - encoding = "utf-8-sig" - text = text.replace("\n", "\r\n") - else: - encoding = "utf-8" - text = text.encode(encoding) - - f = os.fdopen(fd, "wb") - f.write(text) - f.close() - timestamp = os.path.getmtime(name) - - self.edit_file(name) - - if self.require_save and os.path.getmtime(name) == timestamp: - return None - - f = open(name, "rb") - try: - rv = f.read() - finally: - f.close() - return rv.decode("utf-8-sig").replace("\r\n", "\n") - finally: - os.unlink(name) - - -def open_url(url, wait=False, locate=False): - import subprocess - - def _unquote_file(url): - try: - import urllib - except ImportError: - import urllib - if url.startswith("file://"): - url = urllib.unquote(url[7:]) - return url - - if sys.platform == "darwin": - args = ["open"] - if wait: - args.append("-W") - if locate: - args.append("-R") - args.append(_unquote_file(url)) - null = open("/dev/null", "w") - try: - return subprocess.Popen(args, stderr=null).wait() - finally: - null.close() - elif WIN: - if locate: - url = _unquote_file(url) - args = "explorer /select,{}".format(shlex_quote(url)) - else: - args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex_quote(url)) - return os.system(args) - elif CYGWIN: - if locate: - url = _unquote_file(url) - args = "cygstart {}".format(shlex_quote(os.path.dirname(url))) - else: - args = "cygstart {} {}".format("-w" if wait else "", shlex_quote(url)) - return os.system(args) - - try: - if locate: - url = os.path.dirname(_unquote_file(url)) or "." - else: - url = _unquote_file(url) - c = subprocess.Popen(["xdg-open", url]) - if wait: - return c.wait() - return 0 - except OSError: - if url.startswith(("http://", "https://")) and not locate and not wait: - import webbrowser - - webbrowser.open(url) - return 0 - return 1 - - -def _translate_ch_to_exc(ch): - if ch == u"\x03": - raise KeyboardInterrupt() - if ch == u"\x04" and not WIN: # Unix-like, Ctrl+D - raise EOFError() - if ch == u"\x1a" and WIN: # Windows, Ctrl+Z - raise EOFError() - - -if WIN: - import msvcrt - - @contextlib.contextmanager - def raw_terminal(): - yield - - def getchar(echo): - # The function `getch` will return a bytes object corresponding to - # the pressed character. Since Windows 10 build 1803, it will also - # return \x00 when called a second time after pressing a regular key. - # - # `getwch` does not share this probably-bugged behavior. Moreover, it - # returns a Unicode object by default, which is what we want. - # - # Either of these functions will return \x00 or \xe0 to indicate - # a special key, and you need to call the same function again to get - # the "rest" of the code. The fun part is that \u00e0 is - # "latin small letter a with grave", so if you type that on a French - # keyboard, you _also_ get a \xe0. - # E.g., consider the Up arrow. This returns \xe0 and then \x48. The - # resulting Unicode string reads as "a with grave" + "capital H". - # This is indistinguishable from when the user actually types - # "a with grave" and then "capital H". - # - # When \xe0 is returned, we assume it's part of a special-key sequence - # and call `getwch` again, but that means that when the user types - # the \u00e0 character, `getchar` doesn't return until a second - # character is typed. - # The alternative is returning immediately, but that would mess up - # cross-platform handling of arrow keys and others that start with - # \xe0. Another option is using `getch`, but then we can't reliably - # read non-ASCII characters, because return values of `getch` are - # limited to the current 8-bit codepage. - # - # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` - # is doing the right thing in more situations than with `getch`. - if echo: - func = msvcrt.getwche - else: - func = msvcrt.getwch - - rv = func() - if rv in (u"\x00", u"\xe0"): - # \x00 and \xe0 are control characters that indicate special key, - # see above. - rv += func() - _translate_ch_to_exc(rv) - return rv - - -else: - import tty - import termios - - @contextlib.contextmanager - def raw_terminal(): - if not isatty(sys.stdin): - f = open("/dev/tty") - fd = f.fileno() - else: - fd = sys.stdin.fileno() - f = None - try: - old_settings = termios.tcgetattr(fd) - try: - tty.setraw(fd) - yield fd - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stdout.flush() - if f is not None: - f.close() - except termios.error: - pass - - def getchar(echo): - with raw_terminal() as fd: - ch = os.read(fd, 32) - ch = ch.decode(get_best_encoding(sys.stdin), "replace") - if echo and isatty(sys.stdout): - sys.stdout.write(ch) - _translate_ch_to_exc(ch) - return ch diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_textwrap.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_textwrap.py deleted file mode 100644 index 6959087..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_textwrap.py +++ /dev/null @@ -1,37 +0,0 @@ -import textwrap -from contextlib import contextmanager - - -class TextWrapper(textwrap.TextWrapper): - def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): - space_left = max(width - cur_len, 1) - - if self.break_long_words: - last = reversed_chunks[-1] - cut = last[:space_left] - res = last[space_left:] - cur_line.append(cut) - reversed_chunks[-1] = res - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - @contextmanager - def extra_indent(self, indent): - old_initial_indent = self.initial_indent - old_subsequent_indent = self.subsequent_indent - self.initial_indent += indent - self.subsequent_indent += indent - try: - yield - finally: - self.initial_indent = old_initial_indent - self.subsequent_indent = old_subsequent_indent - - def indent_only(self, text): - rv = [] - for idx, line in enumerate(text.splitlines()): - indent = self.initial_indent - if idx > 0: - indent = self.subsequent_indent - rv.append(indent + line) - return "\n".join(rv) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_unicodefun.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_unicodefun.py deleted file mode 100644 index 781c365..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_unicodefun.py +++ /dev/null @@ -1,131 +0,0 @@ -import codecs -import os -import sys - -from ._compat import PY2 - - -def _find_unicode_literals_frame(): - import __future__ - - if not hasattr(sys, "_getframe"): # not all Python implementations have it - return 0 - frm = sys._getframe(1) - idx = 1 - while frm is not None: - if frm.f_globals.get("__name__", "").startswith("click."): - frm = frm.f_back - idx += 1 - elif frm.f_code.co_flags & __future__.unicode_literals.compiler_flag: - return idx - else: - break - return 0 - - -def _check_for_unicode_literals(): - if not __debug__: - return - - from . import disable_unicode_literals_warning - - if not PY2 or disable_unicode_literals_warning: - return - bad_frame = _find_unicode_literals_frame() - if bad_frame <= 0: - return - from warnings import warn - - warn( - Warning( - "Click detected the use of the unicode_literals __future__" - " import. This is heavily discouraged because it can" - " introduce subtle bugs in your code. You should instead" - ' use explicit u"" literals for your unicode strings. For' - " more information see" - " https://click.palletsprojects.com/python3/" - ), - stacklevel=bad_frame, - ) - - -def _verify_python3_env(): - """Ensures that the environment is good for unicode on Python 3.""" - if PY2: - return - try: - import locale - - fs_enc = codecs.lookup(locale.getpreferredencoding()).name - except Exception: - fs_enc = "ascii" - if fs_enc != "ascii": - return - - extra = "" - if os.name == "posix": - import subprocess - - try: - rv = subprocess.Popen( - ["locale", "-a"], stdout=subprocess.PIPE, stderr=subprocess.PIPE - ).communicate()[0] - except OSError: - rv = b"" - good_locales = set() - has_c_utf8 = False - - # Make sure we're operating on text here. - if isinstance(rv, bytes): - rv = rv.decode("ascii", "replace") - - for line in rv.splitlines(): - locale = line.strip() - if locale.lower().endswith((".utf-8", ".utf8")): - good_locales.add(locale) - if locale.lower() in ("c.utf8", "c.utf-8"): - has_c_utf8 = True - - extra += "\n\n" - if not good_locales: - extra += ( - "Additional information: on this system no suitable" - " UTF-8 locales were discovered. This most likely" - " requires resolving by reconfiguring the locale" - " system." - ) - elif has_c_utf8: - extra += ( - "This system supports the C.UTF-8 locale which is" - " recommended. You might be able to resolve your issue" - " by exporting the following environment variables:\n\n" - " export LC_ALL=C.UTF-8\n" - " export LANG=C.UTF-8" - ) - else: - extra += ( - "This system lists a couple of UTF-8 supporting locales" - " that you can pick from. The following suitable" - " locales were discovered: {}".format(", ".join(sorted(good_locales))) - ) - - bad_locale = None - for locale in os.environ.get("LC_ALL"), os.environ.get("LANG"): - if locale and locale.lower().endswith((".utf-8", ".utf8")): - bad_locale = locale - if locale is not None: - break - if bad_locale is not None: - extra += ( - "\n\nClick discovered that you exported a UTF-8 locale" - " but the locale system could not pick up from it" - " because it does not exist. The exported locale is" - " '{}' but it is not supported".format(bad_locale) - ) - - raise RuntimeError( - "Click will abort further execution because Python 3 was" - " configured to use ASCII as encoding for the environment." - " Consult https://click.palletsprojects.com/python3/ for" - " mitigation steps.{}".format(extra) - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_winconsole.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_winconsole.py deleted file mode 100644 index b6c4274..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/_winconsole.py +++ /dev/null @@ -1,370 +0,0 @@ -# -*- coding: utf-8 -*- -# This module is based on the excellent work by Adam Bartoš who -# provided a lot of what went into the implementation here in -# the discussion to issue1602 in the Python bug tracker. -# -# There are some general differences in regards to how this works -# compared to the original patches as we do not need to patch -# the entire interpreter but just work in our little world of -# echo and prmopt. -import ctypes -import io -import os -import sys -import time -import zlib -from ctypes import byref -from ctypes import c_char -from ctypes import c_char_p -from ctypes import c_int -from ctypes import c_ssize_t -from ctypes import c_ulong -from ctypes import c_void_p -from ctypes import POINTER -from ctypes import py_object -from ctypes import windll -from ctypes import WinError -from ctypes import WINFUNCTYPE -from ctypes.wintypes import DWORD -from ctypes.wintypes import HANDLE -from ctypes.wintypes import LPCWSTR -from ctypes.wintypes import LPWSTR - -import msvcrt - -from ._compat import _NonClosingTextIOWrapper -from ._compat import PY2 -from ._compat import text_type - -try: - from ctypes import pythonapi - - PyObject_GetBuffer = pythonapi.PyObject_GetBuffer - PyBuffer_Release = pythonapi.PyBuffer_Release -except ImportError: - pythonapi = None - - -c_ssize_p = POINTER(c_ssize_t) - -kernel32 = windll.kernel32 -GetStdHandle = kernel32.GetStdHandle -ReadConsoleW = kernel32.ReadConsoleW -WriteConsoleW = kernel32.WriteConsoleW -GetConsoleMode = kernel32.GetConsoleMode -GetLastError = kernel32.GetLastError -GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) -CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( - ("CommandLineToArgvW", windll.shell32) -) -LocalFree = WINFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)( - ("LocalFree", windll.kernel32) -) - - -STDIN_HANDLE = GetStdHandle(-10) -STDOUT_HANDLE = GetStdHandle(-11) -STDERR_HANDLE = GetStdHandle(-12) - - -PyBUF_SIMPLE = 0 -PyBUF_WRITABLE = 1 - -ERROR_SUCCESS = 0 -ERROR_NOT_ENOUGH_MEMORY = 8 -ERROR_OPERATION_ABORTED = 995 - -STDIN_FILENO = 0 -STDOUT_FILENO = 1 -STDERR_FILENO = 2 - -EOF = b"\x1a" -MAX_BYTES_WRITTEN = 32767 - - -class Py_buffer(ctypes.Structure): - _fields_ = [ - ("buf", c_void_p), - ("obj", py_object), - ("len", c_ssize_t), - ("itemsize", c_ssize_t), - ("readonly", c_int), - ("ndim", c_int), - ("format", c_char_p), - ("shape", c_ssize_p), - ("strides", c_ssize_p), - ("suboffsets", c_ssize_p), - ("internal", c_void_p), - ] - - if PY2: - _fields_.insert(-1, ("smalltable", c_ssize_t * 2)) - - -# On PyPy we cannot get buffers so our ability to operate here is -# serverly limited. -if pythonapi is None: - get_buffer = None -else: - - def get_buffer(obj, writable=False): - buf = Py_buffer() - flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE - PyObject_GetBuffer(py_object(obj), byref(buf), flags) - try: - buffer_type = c_char * buf.len - return buffer_type.from_address(buf.buf) - finally: - PyBuffer_Release(byref(buf)) - - -class _WindowsConsoleRawIOBase(io.RawIOBase): - def __init__(self, handle): - self.handle = handle - - def isatty(self): - io.RawIOBase.isatty(self) - return True - - -class _WindowsConsoleReader(_WindowsConsoleRawIOBase): - def readable(self): - return True - - def readinto(self, b): - bytes_to_be_read = len(b) - if not bytes_to_be_read: - return 0 - elif bytes_to_be_read % 2: - raise ValueError( - "cannot read odd number of bytes from UTF-16-LE encoded console" - ) - - buffer = get_buffer(b, writable=True) - code_units_to_be_read = bytes_to_be_read // 2 - code_units_read = c_ulong() - - rv = ReadConsoleW( - HANDLE(self.handle), - buffer, - code_units_to_be_read, - byref(code_units_read), - None, - ) - if GetLastError() == ERROR_OPERATION_ABORTED: - # wait for KeyboardInterrupt - time.sleep(0.1) - if not rv: - raise OSError("Windows error: {}".format(GetLastError())) - - if buffer[0] == EOF: - return 0 - return 2 * code_units_read.value - - -class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): - def writable(self): - return True - - @staticmethod - def _get_error_message(errno): - if errno == ERROR_SUCCESS: - return "ERROR_SUCCESS" - elif errno == ERROR_NOT_ENOUGH_MEMORY: - return "ERROR_NOT_ENOUGH_MEMORY" - return "Windows error {}".format(errno) - - def write(self, b): - bytes_to_be_written = len(b) - buf = get_buffer(b) - code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 - code_units_written = c_ulong() - - WriteConsoleW( - HANDLE(self.handle), - buf, - code_units_to_be_written, - byref(code_units_written), - None, - ) - bytes_written = 2 * code_units_written.value - - if bytes_written == 0 and bytes_to_be_written > 0: - raise OSError(self._get_error_message(GetLastError())) - return bytes_written - - -class ConsoleStream(object): - def __init__(self, text_stream, byte_stream): - self._text_stream = text_stream - self.buffer = byte_stream - - @property - def name(self): - return self.buffer.name - - def write(self, x): - if isinstance(x, text_type): - return self._text_stream.write(x) - try: - self.flush() - except Exception: - pass - return self.buffer.write(x) - - def writelines(self, lines): - for line in lines: - self.write(line) - - def __getattr__(self, name): - return getattr(self._text_stream, name) - - def isatty(self): - return self.buffer.isatty() - - def __repr__(self): - return "".format( - self.name, self.encoding - ) - - -class WindowsChunkedWriter(object): - """ - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()' which we wrap to write in - limited chunks due to a Windows limitation on binary console streams. - """ - - def __init__(self, wrapped): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def write(self, text): - total_to_write = len(text) - written = 0 - - while written < total_to_write: - to_write = min(total_to_write - written, MAX_BYTES_WRITTEN) - self.__wrapped.write(text[written : written + to_write]) - written += to_write - - -_wrapped_std_streams = set() - - -def _wrap_std_stream(name): - # Python 2 & Windows 7 and below - if ( - PY2 - and sys.getwindowsversion()[:2] <= (6, 1) - and name not in _wrapped_std_streams - ): - setattr(sys, name, WindowsChunkedWriter(getattr(sys, name))) - _wrapped_std_streams.add(name) - - -def _get_text_stdin(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return ConsoleStream(text_stream, buffer_stream) - - -def _get_text_stdout(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return ConsoleStream(text_stream, buffer_stream) - - -def _get_text_stderr(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return ConsoleStream(text_stream, buffer_stream) - - -if PY2: - - def _hash_py_argv(): - return zlib.crc32("\x00".join(sys.argv[1:])) - - _initial_argv_hash = _hash_py_argv() - - def _get_windows_argv(): - argc = c_int(0) - argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) - if not argv_unicode: - raise WinError() - try: - argv = [argv_unicode[i] for i in range(0, argc.value)] - finally: - LocalFree(argv_unicode) - del argv_unicode - - if not hasattr(sys, "frozen"): - argv = argv[1:] - while len(argv) > 0: - arg = argv[0] - if not arg.startswith("-") or arg == "-": - break - argv = argv[1:] - if arg.startswith(("-c", "-m")): - break - - return argv[1:] - - -_stream_factories = { - 0: _get_text_stdin, - 1: _get_text_stdout, - 2: _get_text_stderr, -} - - -def _is_console(f): - if not hasattr(f, "fileno"): - return False - - try: - fileno = f.fileno() - except OSError: - return False - - handle = msvcrt.get_osfhandle(fileno) - return bool(GetConsoleMode(handle, byref(DWORD()))) - - -def _get_windows_console_stream(f, encoding, errors): - if ( - get_buffer is not None - and encoding in ("utf-16-le", None) - and errors in ("strict", None) - and _is_console(f) - ): - func = _stream_factories.get(f.fileno()) - if func is not None: - if not PY2: - f = getattr(f, "buffer", None) - if f is None: - return None - else: - # If we are on Python 2 we need to set the stream that we - # deal with to binary mode as otherwise the exercise if a - # bit moot. The same problems apply as for - # get_binary_stdin and friends from _compat. - msvcrt.setmode(f.fileno(), os.O_BINARY) - return func(f) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/core.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/core.py deleted file mode 100644 index f58bf26..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/core.py +++ /dev/null @@ -1,2030 +0,0 @@ -import errno -import inspect -import os -import sys -from contextlib import contextmanager -from functools import update_wrapper -from itertools import repeat - -from ._compat import isidentifier -from ._compat import iteritems -from ._compat import PY2 -from ._compat import string_types -from ._unicodefun import _check_for_unicode_literals -from ._unicodefun import _verify_python3_env -from .exceptions import Abort -from .exceptions import BadParameter -from .exceptions import ClickException -from .exceptions import Exit -from .exceptions import MissingParameter -from .exceptions import UsageError -from .formatting import HelpFormatter -from .formatting import join_options -from .globals import pop_context -from .globals import push_context -from .parser import OptionParser -from .parser import split_opt -from .termui import confirm -from .termui import prompt -from .termui import style -from .types import BOOL -from .types import convert_type -from .types import IntRange -from .utils import echo -from .utils import get_os_args -from .utils import make_default_short_help -from .utils import make_str -from .utils import PacifyFlushWrapper - -_missing = object() - -SUBCOMMAND_METAVAR = "COMMAND [ARGS]..." -SUBCOMMANDS_METAVAR = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." - -DEPRECATED_HELP_NOTICE = " (DEPRECATED)" -DEPRECATED_INVOKE_NOTICE = "DeprecationWarning: The command %(name)s is deprecated." - - -def _maybe_show_deprecated_notice(cmd): - if cmd.deprecated: - echo(style(DEPRECATED_INVOKE_NOTICE % {"name": cmd.name}, fg="red"), err=True) - - -def fast_exit(code): - """Exit without garbage collection, this speeds up exit by about 10ms for - things like bash completion. - """ - sys.stdout.flush() - sys.stderr.flush() - os._exit(code) - - -def _bashcomplete(cmd, prog_name, complete_var=None): - """Internal handler for the bash completion support.""" - if complete_var is None: - complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) - complete_instr = os.environ.get(complete_var) - if not complete_instr: - return - - from ._bashcomplete import bashcomplete - - if bashcomplete(cmd, prog_name, complete_var, complete_instr): - fast_exit(1) - - -def _check_multicommand(base_command, cmd_name, cmd, register=False): - if not base_command.chain or not isinstance(cmd, MultiCommand): - return - if register: - hint = ( - "It is not possible to add multi commands as children to" - " another multi command that is in chain mode." - ) - else: - hint = ( - "Found a multi command as subcommand to a multi command" - " that is in chain mode. This is not supported." - ) - raise RuntimeError( - "{}. Command '{}' is set to chain and '{}' was added as" - " subcommand but it in itself is a multi command. ('{}' is a {}" - " within a chained {} named '{}').".format( - hint, - base_command.name, - cmd_name, - cmd_name, - cmd.__class__.__name__, - base_command.__class__.__name__, - base_command.name, - ) - ) - - -def batch(iterable, batch_size): - return list(zip(*repeat(iter(iterable), batch_size))) - - -def invoke_param_callback(callback, ctx, param, value): - code = getattr(callback, "__code__", None) - args = getattr(code, "co_argcount", 3) - - if args < 3: - from warnings import warn - - warn( - "Parameter callbacks take 3 args, (ctx, param, value). The" - " 2-arg style is deprecated and will be removed in 8.0.".format(callback), - DeprecationWarning, - stacklevel=3, - ) - return callback(ctx, value) - - return callback(ctx, param, value) - - -@contextmanager -def augment_usage_errors(ctx, param=None): - """Context manager that attaches extra information to exceptions.""" - try: - yield - except BadParameter as e: - if e.ctx is None: - e.ctx = ctx - if param is not None and e.param is None: - e.param = param - raise - except UsageError as e: - if e.ctx is None: - e.ctx = ctx - raise - - -def iter_params_for_processing(invocation_order, declaration_order): - """Given a sequence of parameters in the order as should be considered - for processing and an iterable of parameters that exist, this returns - a list in the correct order as they should be processed. - """ - - def sort_key(item): - try: - idx = invocation_order.index(item) - except ValueError: - idx = float("inf") - return (not item.is_eager, idx) - - return sorted(declaration_order, key=sort_key) - - -class Context(object): - """The context is a special internal object that holds state relevant - for the script execution at every single level. It's normally invisible - to commands unless they opt-in to getting access to it. - - The context is useful as it can pass internal objects around and can - control special execution features such as reading data from - environment variables. - - A context can be used as context manager in which case it will call - :meth:`close` on teardown. - - .. versionadded:: 2.0 - Added the `resilient_parsing`, `help_option_names`, - `token_normalize_func` parameters. - - .. versionadded:: 3.0 - Added the `allow_extra_args` and `allow_interspersed_args` - parameters. - - .. versionadded:: 4.0 - Added the `color`, `ignore_unknown_options`, and - `max_content_width` parameters. - - .. versionadded:: 7.1 - Added the `show_default` parameter. - - :param command: the command class for this context. - :param parent: the parent context. - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it is usually - the name of the script, for commands below it it's - the name of the script. - :param obj: an arbitrary object of user data. - :param auto_envvar_prefix: the prefix to use for automatic environment - variables. If this is `None` then reading - from environment variables is disabled. This - does not affect manually set environment - variables which are always read. - :param default_map: a dictionary (like object) with default values - for parameters. - :param terminal_width: the width of the terminal. The default is - inherit from parent context. If no context - defines the terminal width then auto - detection will be applied. - :param max_content_width: the maximum width for content rendered by - Click (this currently only affects help - pages). This defaults to 80 characters if - not overridden. In other words: even if the - terminal is larger than that, Click will not - format things wider than 80 characters by - default. In addition to that, formatters might - add some safety mapping on the right. - :param resilient_parsing: if this flag is enabled then Click will - parse without any interactivity or callback - invocation. Default values will also be - ignored. This is useful for implementing - things such as completion support. - :param allow_extra_args: if this is set to `True` then extra arguments - at the end will not raise an error and will be - kept on the context. The default is to inherit - from the command. - :param allow_interspersed_args: if this is set to `False` then options - and arguments cannot be mixed. The - default is to inherit from the command. - :param ignore_unknown_options: instructs click to ignore options it does - not know and keeps them for later - processing. - :param help_option_names: optionally a list of strings that define how - the default help parameter is named. The - default is ``['--help']``. - :param token_normalize_func: an optional function that is used to - normalize tokens (options, choices, - etc.). This for instance can be used to - implement case insensitive behavior. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are used in texts that Click prints which is by - default not the case. This for instance would affect - help output. - :param show_default: if True, shows defaults for all options. - Even if an option is later created with show_default=False, - this command-level setting overrides it. - """ - - def __init__( - self, - command, - parent=None, - info_name=None, - obj=None, - auto_envvar_prefix=None, - default_map=None, - terminal_width=None, - max_content_width=None, - resilient_parsing=False, - allow_extra_args=None, - allow_interspersed_args=None, - ignore_unknown_options=None, - help_option_names=None, - token_normalize_func=None, - color=None, - show_default=None, - ): - #: the parent context or `None` if none exists. - self.parent = parent - #: the :class:`Command` for this context. - self.command = command - #: the descriptive information name - self.info_name = info_name - #: the parsed parameters except if the value is hidden in which - #: case it's not remembered. - self.params = {} - #: the leftover arguments. - self.args = [] - #: protected arguments. These are arguments that are prepended - #: to `args` when certain parsing scenarios are encountered but - #: must be never propagated to another arguments. This is used - #: to implement nested parsing. - self.protected_args = [] - if obj is None and parent is not None: - obj = parent.obj - #: the user object stored. - self.obj = obj - self._meta = getattr(parent, "meta", {}) - - #: A dictionary (-like object) with defaults for parameters. - if ( - default_map is None - and parent is not None - and parent.default_map is not None - ): - default_map = parent.default_map.get(info_name) - self.default_map = default_map - - #: This flag indicates if a subcommand is going to be executed. A - #: group callback can use this information to figure out if it's - #: being executed directly or because the execution flow passes - #: onwards to a subcommand. By default it's None, but it can be - #: the name of the subcommand to execute. - #: - #: If chaining is enabled this will be set to ``'*'`` in case - #: any commands are executed. It is however not possible to - #: figure out which ones. If you require this knowledge you - #: should use a :func:`resultcallback`. - self.invoked_subcommand = None - - if terminal_width is None and parent is not None: - terminal_width = parent.terminal_width - #: The width of the terminal (None is autodetection). - self.terminal_width = terminal_width - - if max_content_width is None and parent is not None: - max_content_width = parent.max_content_width - #: The maximum width of formatted content (None implies a sensible - #: default which is 80 for most things). - self.max_content_width = max_content_width - - if allow_extra_args is None: - allow_extra_args = command.allow_extra_args - #: Indicates if the context allows extra args or if it should - #: fail on parsing. - #: - #: .. versionadded:: 3.0 - self.allow_extra_args = allow_extra_args - - if allow_interspersed_args is None: - allow_interspersed_args = command.allow_interspersed_args - #: Indicates if the context allows mixing of arguments and - #: options or not. - #: - #: .. versionadded:: 3.0 - self.allow_interspersed_args = allow_interspersed_args - - if ignore_unknown_options is None: - ignore_unknown_options = command.ignore_unknown_options - #: Instructs click to ignore options that a command does not - #: understand and will store it on the context for later - #: processing. This is primarily useful for situations where you - #: want to call into external programs. Generally this pattern is - #: strongly discouraged because it's not possibly to losslessly - #: forward all arguments. - #: - #: .. versionadded:: 4.0 - self.ignore_unknown_options = ignore_unknown_options - - if help_option_names is None: - if parent is not None: - help_option_names = parent.help_option_names - else: - help_option_names = ["--help"] - - #: The names for the help options. - self.help_option_names = help_option_names - - if token_normalize_func is None and parent is not None: - token_normalize_func = parent.token_normalize_func - - #: An optional normalization function for tokens. This is - #: options, choices, commands etc. - self.token_normalize_func = token_normalize_func - - #: Indicates if resilient parsing is enabled. In that case Click - #: will do its best to not cause any failures and default values - #: will be ignored. Useful for completion. - self.resilient_parsing = resilient_parsing - - # If there is no envvar prefix yet, but the parent has one and - # the command on this level has a name, we can expand the envvar - # prefix automatically. - if auto_envvar_prefix is None: - if ( - parent is not None - and parent.auto_envvar_prefix is not None - and self.info_name is not None - ): - auto_envvar_prefix = "{}_{}".format( - parent.auto_envvar_prefix, self.info_name.upper() - ) - else: - auto_envvar_prefix = auto_envvar_prefix.upper() - if auto_envvar_prefix is not None: - auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") - self.auto_envvar_prefix = auto_envvar_prefix - - if color is None and parent is not None: - color = parent.color - - #: Controls if styling output is wanted or not. - self.color = color - - self.show_default = show_default - - self._close_callbacks = [] - self._depth = 0 - - def __enter__(self): - self._depth += 1 - push_context(self) - return self - - def __exit__(self, exc_type, exc_value, tb): - self._depth -= 1 - if self._depth == 0: - self.close() - pop_context() - - @contextmanager - def scope(self, cleanup=True): - """This helper method can be used with the context object to promote - it to the current thread local (see :func:`get_current_context`). - The default behavior of this is to invoke the cleanup functions which - can be disabled by setting `cleanup` to `False`. The cleanup - functions are typically used for things such as closing file handles. - - If the cleanup is intended the context object can also be directly - used as a context manager. - - Example usage:: - - with ctx.scope(): - assert get_current_context() is ctx - - This is equivalent:: - - with ctx: - assert get_current_context() is ctx - - .. versionadded:: 5.0 - - :param cleanup: controls if the cleanup functions should be run or - not. The default is to run these functions. In - some situations the context only wants to be - temporarily pushed in which case this can be disabled. - Nested pushes automatically defer the cleanup. - """ - if not cleanup: - self._depth += 1 - try: - with self as rv: - yield rv - finally: - if not cleanup: - self._depth -= 1 - - @property - def meta(self): - """This is a dictionary which is shared with all the contexts - that are nested. It exists so that click utilities can store some - state here if they need to. It is however the responsibility of - that code to manage this dictionary well. - - The keys are supposed to be unique dotted strings. For instance - module paths are a good choice for it. What is stored in there is - irrelevant for the operation of click. However what is important is - that code that places data here adheres to the general semantics of - the system. - - Example usage:: - - LANG_KEY = f'{__name__}.lang' - - def set_language(value): - ctx = get_current_context() - ctx.meta[LANG_KEY] = value - - def get_language(): - return get_current_context().meta.get(LANG_KEY, 'en_US') - - .. versionadded:: 5.0 - """ - return self._meta - - def make_formatter(self): - """Creates the formatter for the help and usage output.""" - return HelpFormatter( - width=self.terminal_width, max_width=self.max_content_width - ) - - def call_on_close(self, f): - """This decorator remembers a function as callback that should be - executed when the context tears down. This is most useful to bind - resource handling to the script execution. For instance, file objects - opened by the :class:`File` type will register their close callbacks - here. - - :param f: the function to execute on teardown. - """ - self._close_callbacks.append(f) - return f - - def close(self): - """Invokes all close callbacks.""" - for cb in self._close_callbacks: - cb() - self._close_callbacks = [] - - @property - def command_path(self): - """The computed command path. This is used for the ``usage`` - information on the help page. It's automatically created by - combining the info names of the chain of contexts to the root. - """ - rv = "" - if self.info_name is not None: - rv = self.info_name - if self.parent is not None: - rv = "{} {}".format(self.parent.command_path, rv) - return rv.lstrip() - - def find_root(self): - """Finds the outermost context.""" - node = self - while node.parent is not None: - node = node.parent - return node - - def find_object(self, object_type): - """Finds the closest object of a given type.""" - node = self - while node is not None: - if isinstance(node.obj, object_type): - return node.obj - node = node.parent - - def ensure_object(self, object_type): - """Like :meth:`find_object` but sets the innermost object to a - new instance of `object_type` if it does not exist. - """ - rv = self.find_object(object_type) - if rv is None: - self.obj = rv = object_type() - return rv - - def lookup_default(self, name): - """Looks up the default for a parameter name. This by default - looks into the :attr:`default_map` if available. - """ - if self.default_map is not None: - rv = self.default_map.get(name) - if callable(rv): - rv = rv() - return rv - - def fail(self, message): - """Aborts the execution of the program with a specific error - message. - - :param message: the error message to fail with. - """ - raise UsageError(message, self) - - def abort(self): - """Aborts the script.""" - raise Abort() - - def exit(self, code=0): - """Exits the application with a given exit code.""" - raise Exit(code) - - def get_usage(self): - """Helper method to get formatted usage string for the current - context and command. - """ - return self.command.get_usage(self) - - def get_help(self): - """Helper method to get formatted help page for the current - context and command. - """ - return self.command.get_help(self) - - def invoke(*args, **kwargs): # noqa: B902 - """Invokes a command callback in exactly the way it expects. There - are two ways to invoke this method: - - 1. the first argument can be a callback and all other arguments and - keyword arguments are forwarded directly to the function. - 2. the first argument is a click command object. In that case all - arguments are forwarded as well but proper click parameters - (options and click arguments) must be keyword arguments and Click - will fill in defaults. - - Note that before Click 3.2 keyword arguments were not properly filled - in against the intention of this code and no context was created. For - more information about this change and why it was done in a bugfix - release see :ref:`upgrade-to-3.2`. - """ - self, callback = args[:2] - ctx = self - - # It's also possible to invoke another command which might or - # might not have a callback. In that case we also fill - # in defaults and make a new context for this command. - if isinstance(callback, Command): - other_cmd = callback - callback = other_cmd.callback - ctx = Context(other_cmd, info_name=other_cmd.name, parent=self) - if callback is None: - raise TypeError( - "The given command does not have a callback that can be invoked." - ) - - for param in other_cmd.params: - if param.name not in kwargs and param.expose_value: - kwargs[param.name] = param.get_default(ctx) - - args = args[2:] - with augment_usage_errors(self): - with ctx: - return callback(*args, **kwargs) - - def forward(*args, **kwargs): # noqa: B902 - """Similar to :meth:`invoke` but fills in default keyword - arguments from the current context if the other command expects - it. This cannot invoke callbacks directly, only other commands. - """ - self, cmd = args[:2] - - # It's also possible to invoke another command which might or - # might not have a callback. - if not isinstance(cmd, Command): - raise TypeError("Callback is not a command.") - - for param in self.params: - if param not in kwargs: - kwargs[param] = self.params[param] - - return self.invoke(cmd, **kwargs) - - -class BaseCommand(object): - """The base command implements the minimal API contract of commands. - Most code will never use this as it does not implement a lot of useful - functionality but it can act as the direct subclass of alternative - parsing methods that do not depend on the Click parser. - - For instance, this can be used to bridge Click and other systems like - argparse or docopt. - - Because base commands do not implement a lot of the API that other - parts of Click take for granted, they are not supported for all - operations. For instance, they cannot be used with the decorators - usually and they have no built-in callback system. - - .. versionchanged:: 2.0 - Added the `context_settings` parameter. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - """ - - #: the default for the :attr:`Context.allow_extra_args` flag. - allow_extra_args = False - #: the default for the :attr:`Context.allow_interspersed_args` flag. - allow_interspersed_args = True - #: the default for the :attr:`Context.ignore_unknown_options` flag. - ignore_unknown_options = False - - def __init__(self, name, context_settings=None): - #: the name the command thinks it has. Upon registering a command - #: on a :class:`Group` the group will default the command name - #: with this information. You should instead use the - #: :class:`Context`\'s :attr:`~Context.info_name` attribute. - self.name = name - if context_settings is None: - context_settings = {} - #: an optional dictionary with defaults passed to the context. - self.context_settings = context_settings - - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, self.name) - - def get_usage(self, ctx): - raise NotImplementedError("Base commands cannot get usage") - - def get_help(self, ctx): - raise NotImplementedError("Base commands cannot get help") - - def make_context(self, info_name, args, parent=None, **extra): - """This function when given an info name and arguments will kick - off the parsing and create a new :class:`Context`. It does not - invoke the actual command callback though. - - :param info_name: the info name for this invokation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it's usually - the name of the script, for commands below it it's - the name of the script. - :param args: the arguments to parse as list of strings. - :param parent: the parent context if available. - :param extra: extra keyword arguments forwarded to the context - constructor. - """ - for key, value in iteritems(self.context_settings): - if key not in extra: - extra[key] = value - ctx = Context(self, info_name=info_name, parent=parent, **extra) - with ctx.scope(cleanup=False): - self.parse_args(ctx, args) - return ctx - - def parse_args(self, ctx, args): - """Given a context and a list of arguments this creates the parser - and parses the arguments, then modifies the context as necessary. - This is automatically invoked by :meth:`make_context`. - """ - raise NotImplementedError("Base commands do not know how to parse arguments.") - - def invoke(self, ctx): - """Given a context, this invokes the command. The default - implementation is raising a not implemented error. - """ - raise NotImplementedError("Base commands are not invokable by default") - - def main( - self, - args=None, - prog_name=None, - complete_var=None, - standalone_mode=True, - **extra - ): - """This is the way to invoke a script with all the bells and - whistles as a command line application. This will always terminate - the application after a call. If this is not wanted, ``SystemExit`` - needs to be caught. - - This method is also available by directly calling the instance of - a :class:`Command`. - - .. versionadded:: 3.0 - Added the `standalone_mode` flag to control the standalone mode. - - :param args: the arguments that should be used for parsing. If not - provided, ``sys.argv[1:]`` is used. - :param prog_name: the program name that should be used. By default - the program name is constructed by taking the file - name from ``sys.argv[0]``. - :param complete_var: the environment variable that controls the - bash completion support. The default is - ``"__COMPLETE"`` with prog_name in - uppercase. - :param standalone_mode: the default behavior is to invoke the script - in standalone mode. Click will then - handle exceptions and convert them into - error messages and the function will never - return but shut down the interpreter. If - this is set to `False` they will be - propagated to the caller and the return - value of this function is the return value - of :meth:`invoke`. - :param extra: extra keyword arguments are forwarded to the context - constructor. See :class:`Context` for more information. - """ - # If we are in Python 3, we will verify that the environment is - # sane at this point or reject further execution to avoid a - # broken script. - if not PY2: - _verify_python3_env() - else: - _check_for_unicode_literals() - - if args is None: - args = get_os_args() - else: - args = list(args) - - if prog_name is None: - prog_name = make_str( - os.path.basename(sys.argv[0] if sys.argv else __file__) - ) - - # Hook for the Bash completion. This only activates if the Bash - # completion is actually enabled, otherwise this is quite a fast - # noop. - _bashcomplete(self, prog_name, complete_var) - - try: - try: - with self.make_context(prog_name, args, **extra) as ctx: - rv = self.invoke(ctx) - if not standalone_mode: - return rv - # it's not safe to `ctx.exit(rv)` here! - # note that `rv` may actually contain data like "1" which - # has obvious effects - # more subtle case: `rv=[None, None]` can come out of - # chained commands which all returned `None` -- so it's not - # even always obvious that `rv` indicates success/failure - # by its truthiness/falsiness - ctx.exit() - except (EOFError, KeyboardInterrupt): - echo(file=sys.stderr) - raise Abort() - except ClickException as e: - if not standalone_mode: - raise - e.show() - sys.exit(e.exit_code) - except IOError as e: - if e.errno == errno.EPIPE: - sys.stdout = PacifyFlushWrapper(sys.stdout) - sys.stderr = PacifyFlushWrapper(sys.stderr) - sys.exit(1) - else: - raise - except Exit as e: - if standalone_mode: - sys.exit(e.exit_code) - else: - # in non-standalone mode, return the exit code - # note that this is only reached if `self.invoke` above raises - # an Exit explicitly -- thus bypassing the check there which - # would return its result - # the results of non-standalone execution may therefore be - # somewhat ambiguous: if there are codepaths which lead to - # `ctx.exit(1)` and to `return 1`, the caller won't be able to - # tell the difference between the two - return e.exit_code - except Abort: - if not standalone_mode: - raise - echo("Aborted!", file=sys.stderr) - sys.exit(1) - - def __call__(self, *args, **kwargs): - """Alias for :meth:`main`.""" - return self.main(*args, **kwargs) - - -class Command(BaseCommand): - """Commands are the basic building block of command line interfaces in - Click. A basic command handles command line parsing and might dispatch - more parsing to commands nested below it. - - .. versionchanged:: 2.0 - Added the `context_settings` parameter. - .. versionchanged:: 7.1 - Added the `no_args_is_help` parameter. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - :param callback: the callback to invoke. This is optional. - :param params: the parameters to register with this command. This can - be either :class:`Option` or :class:`Argument` objects. - :param help: the help string to use for this command. - :param epilog: like the help string but it's printed at the end of the - help page after everything else. - :param short_help: the short help to use for this command. This is - shown on the command listing of the parent command. - :param add_help_option: by default each command registers a ``--help`` - option. This can be disabled by this parameter. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is disabled by default. - If enabled this will add ``--help`` as argument - if no arguments are passed - :param hidden: hide this command from help outputs. - - :param deprecated: issues a message indicating that - the command is deprecated. - """ - - def __init__( - self, - name, - context_settings=None, - callback=None, - params=None, - help=None, - epilog=None, - short_help=None, - options_metavar="[OPTIONS]", - add_help_option=True, - no_args_is_help=False, - hidden=False, - deprecated=False, - ): - BaseCommand.__init__(self, name, context_settings) - #: the callback to execute when the command fires. This might be - #: `None` in which case nothing happens. - self.callback = callback - #: the list of parameters for this command in the order they - #: should show up in the help page and execute. Eager parameters - #: will automatically be handled before non eager ones. - self.params = params or [] - # if a form feed (page break) is found in the help text, truncate help - # text to the content preceding the first form feed - if help and "\f" in help: - help = help.split("\f", 1)[0] - self.help = help - self.epilog = epilog - self.options_metavar = options_metavar - self.short_help = short_help - self.add_help_option = add_help_option - self.no_args_is_help = no_args_is_help - self.hidden = hidden - self.deprecated = deprecated - - def get_usage(self, ctx): - """Formats the usage line into a string and returns it. - - Calls :meth:`format_usage` internally. - """ - formatter = ctx.make_formatter() - self.format_usage(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_params(self, ctx): - rv = self.params - help_option = self.get_help_option(ctx) - if help_option is not None: - rv = rv + [help_option] - return rv - - def format_usage(self, ctx, formatter): - """Writes the usage line into the formatter. - - This is a low-level method called by :meth:`get_usage`. - """ - pieces = self.collect_usage_pieces(ctx) - formatter.write_usage(ctx.command_path, " ".join(pieces)) - - def collect_usage_pieces(self, ctx): - """Returns all the pieces that go into the usage line and returns - it as a list of strings. - """ - rv = [self.options_metavar] - for param in self.get_params(ctx): - rv.extend(param.get_usage_pieces(ctx)) - return rv - - def get_help_option_names(self, ctx): - """Returns the names for the help option.""" - all_names = set(ctx.help_option_names) - for param in self.params: - all_names.difference_update(param.opts) - all_names.difference_update(param.secondary_opts) - return all_names - - def get_help_option(self, ctx): - """Returns the help option object.""" - help_options = self.get_help_option_names(ctx) - if not help_options or not self.add_help_option: - return - - def show_help(ctx, param, value): - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - return Option( - help_options, - is_flag=True, - is_eager=True, - expose_value=False, - callback=show_help, - help="Show this message and exit.", - ) - - def make_parser(self, ctx): - """Creates the underlying option parser for this command.""" - parser = OptionParser(ctx) - for param in self.get_params(ctx): - param.add_to_parser(parser, ctx) - return parser - - def get_help(self, ctx): - """Formats the help into a string and returns it. - - Calls :meth:`format_help` internally. - """ - formatter = ctx.make_formatter() - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_short_help_str(self, limit=45): - """Gets short help for the command or makes it by shortening the - long help string. - """ - return ( - self.short_help - or self.help - and make_default_short_help(self.help, limit) - or "" - ) - - def format_help(self, ctx, formatter): - """Writes the help into the formatter if it exists. - - This is a low-level method called by :meth:`get_help`. - - This calls the following methods: - - - :meth:`format_usage` - - :meth:`format_help_text` - - :meth:`format_options` - - :meth:`format_epilog` - """ - self.format_usage(ctx, formatter) - self.format_help_text(ctx, formatter) - self.format_options(ctx, formatter) - self.format_epilog(ctx, formatter) - - def format_help_text(self, ctx, formatter): - """Writes the help text to the formatter if it exists.""" - if self.help: - formatter.write_paragraph() - with formatter.indentation(): - help_text = self.help - if self.deprecated: - help_text += DEPRECATED_HELP_NOTICE - formatter.write_text(help_text) - elif self.deprecated: - formatter.write_paragraph() - with formatter.indentation(): - formatter.write_text(DEPRECATED_HELP_NOTICE) - - def format_options(self, ctx, formatter): - """Writes all the options into the formatter if they exist.""" - opts = [] - for param in self.get_params(ctx): - rv = param.get_help_record(ctx) - if rv is not None: - opts.append(rv) - - if opts: - with formatter.section("Options"): - formatter.write_dl(opts) - - def format_epilog(self, ctx, formatter): - """Writes the epilog into the formatter if it exists.""" - if self.epilog: - formatter.write_paragraph() - with formatter.indentation(): - formatter.write_text(self.epilog) - - def parse_args(self, ctx, args): - if not args and self.no_args_is_help and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - parser = self.make_parser(ctx) - opts, args, param_order = parser.parse_args(args=args) - - for param in iter_params_for_processing(param_order, self.get_params(ctx)): - value, args = param.handle_parse_result(ctx, opts, args) - - if args and not ctx.allow_extra_args and not ctx.resilient_parsing: - ctx.fail( - "Got unexpected extra argument{} ({})".format( - "s" if len(args) != 1 else "", " ".join(map(make_str, args)) - ) - ) - - ctx.args = args - return args - - def invoke(self, ctx): - """Given a context, this invokes the attached callback (if it exists) - in the right way. - """ - _maybe_show_deprecated_notice(self) - if self.callback is not None: - return ctx.invoke(self.callback, **ctx.params) - - -class MultiCommand(Command): - """A multi command is the basic implementation of a command that - dispatches to subcommands. The most common version is the - :class:`Group`. - - :param invoke_without_command: this controls how the multi command itself - is invoked. By default it's only invoked - if a subcommand is provided. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is enabled by default if - `invoke_without_command` is disabled or disabled - if it's enabled. If enabled this will add - ``--help`` as argument if no arguments are - passed. - :param subcommand_metavar: the string that is used in the documentation - to indicate the subcommand place. - :param chain: if this is set to `True` chaining of multiple subcommands - is enabled. This restricts the form of commands in that - they cannot have optional arguments but it allows - multiple commands to be chained together. - :param result_callback: the result callback to attach to this multi - command. - """ - - allow_extra_args = True - allow_interspersed_args = False - - def __init__( - self, - name=None, - invoke_without_command=False, - no_args_is_help=None, - subcommand_metavar=None, - chain=False, - result_callback=None, - **attrs - ): - Command.__init__(self, name, **attrs) - if no_args_is_help is None: - no_args_is_help = not invoke_without_command - self.no_args_is_help = no_args_is_help - self.invoke_without_command = invoke_without_command - if subcommand_metavar is None: - if chain: - subcommand_metavar = SUBCOMMANDS_METAVAR - else: - subcommand_metavar = SUBCOMMAND_METAVAR - self.subcommand_metavar = subcommand_metavar - self.chain = chain - #: The result callback that is stored. This can be set or - #: overridden with the :func:`resultcallback` decorator. - self.result_callback = result_callback - - if self.chain: - for param in self.params: - if isinstance(param, Argument) and not param.required: - raise RuntimeError( - "Multi commands in chain mode cannot have" - " optional arguments." - ) - - def collect_usage_pieces(self, ctx): - rv = Command.collect_usage_pieces(self, ctx) - rv.append(self.subcommand_metavar) - return rv - - def format_options(self, ctx, formatter): - Command.format_options(self, ctx, formatter) - self.format_commands(ctx, formatter) - - def resultcallback(self, replace=False): - """Adds a result callback to the chain command. By default if a - result callback is already registered this will chain them but - this can be disabled with the `replace` parameter. The result - callback is invoked with the return value of the subcommand - (or the list of return values from all subcommands if chaining - is enabled) as well as the parameters as they would be passed - to the main callback. - - Example:: - - @click.group() - @click.option('-i', '--input', default=23) - def cli(input): - return 42 - - @cli.resultcallback() - def process_result(result, input): - return result + input - - .. versionadded:: 3.0 - - :param replace: if set to `True` an already existing result - callback will be removed. - """ - - def decorator(f): - old_callback = self.result_callback - if old_callback is None or replace: - self.result_callback = f - return f - - def function(__value, *args, **kwargs): - return f(old_callback(__value, *args, **kwargs), *args, **kwargs) - - self.result_callback = rv = update_wrapper(function, f) - return rv - - return decorator - - def format_commands(self, ctx, formatter): - """Extra format methods for multi methods that adds all the commands - after the options. - """ - commands = [] - for subcommand in self.list_commands(ctx): - cmd = self.get_command(ctx, subcommand) - # What is this, the tool lied about a command. Ignore it - if cmd is None: - continue - if cmd.hidden: - continue - - commands.append((subcommand, cmd)) - - # allow for 3 times the default spacing - if len(commands): - limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) - - rows = [] - for subcommand, cmd in commands: - help = cmd.get_short_help_str(limit) - rows.append((subcommand, help)) - - if rows: - with formatter.section("Commands"): - formatter.write_dl(rows) - - def parse_args(self, ctx, args): - if not args and self.no_args_is_help and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - rest = Command.parse_args(self, ctx, args) - if self.chain: - ctx.protected_args = rest - ctx.args = [] - elif rest: - ctx.protected_args, ctx.args = rest[:1], rest[1:] - - return ctx.args - - def invoke(self, ctx): - def _process_result(value): - if self.result_callback is not None: - value = ctx.invoke(self.result_callback, value, **ctx.params) - return value - - if not ctx.protected_args: - # If we are invoked without command the chain flag controls - # how this happens. If we are not in chain mode, the return - # value here is the return value of the command. - # If however we are in chain mode, the return value is the - # return value of the result processor invoked with an empty - # list (which means that no subcommand actually was executed). - if self.invoke_without_command: - if not self.chain: - return Command.invoke(self, ctx) - with ctx: - Command.invoke(self, ctx) - return _process_result([]) - ctx.fail("Missing command.") - - # Fetch args back out - args = ctx.protected_args + ctx.args - ctx.args = [] - ctx.protected_args = [] - - # If we're not in chain mode, we only allow the invocation of a - # single command but we also inform the current context about the - # name of the command to invoke. - if not self.chain: - # Make sure the context is entered so we do not clean up - # resources until the result processor has worked. - with ctx: - cmd_name, cmd, args = self.resolve_command(ctx, args) - ctx.invoked_subcommand = cmd_name - Command.invoke(self, ctx) - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) - with sub_ctx: - return _process_result(sub_ctx.command.invoke(sub_ctx)) - - # In chain mode we create the contexts step by step, but after the - # base command has been invoked. Because at that point we do not - # know the subcommands yet, the invoked subcommand attribute is - # set to ``*`` to inform the command that subcommands are executed - # but nothing else. - with ctx: - ctx.invoked_subcommand = "*" if args else None - Command.invoke(self, ctx) - - # Otherwise we make every single context and invoke them in a - # chain. In that case the return value to the result processor - # is the list of all invoked subcommand's results. - contexts = [] - while args: - cmd_name, cmd, args = self.resolve_command(ctx, args) - sub_ctx = cmd.make_context( - cmd_name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - ) - contexts.append(sub_ctx) - args, sub_ctx.args = sub_ctx.args, [] - - rv = [] - for sub_ctx in contexts: - with sub_ctx: - rv.append(sub_ctx.command.invoke(sub_ctx)) - return _process_result(rv) - - def resolve_command(self, ctx, args): - cmd_name = make_str(args[0]) - original_cmd_name = cmd_name - - # Get the command - cmd = self.get_command(ctx, cmd_name) - - # If we can't find the command but there is a normalization - # function available, we try with that one. - if cmd is None and ctx.token_normalize_func is not None: - cmd_name = ctx.token_normalize_func(cmd_name) - cmd = self.get_command(ctx, cmd_name) - - # If we don't find the command we want to show an error message - # to the user that it was not provided. However, there is - # something else we should do: if the first argument looks like - # an option we want to kick off parsing again for arguments to - # resolve things like --help which now should go to the main - # place. - if cmd is None and not ctx.resilient_parsing: - if split_opt(cmd_name)[0]: - self.parse_args(ctx, ctx.args) - ctx.fail("No such command '{}'.".format(original_cmd_name)) - - return cmd_name, cmd, args[1:] - - def get_command(self, ctx, cmd_name): - """Given a context and a command name, this returns a - :class:`Command` object if it exists or returns `None`. - """ - raise NotImplementedError() - - def list_commands(self, ctx): - """Returns a list of subcommand names in the order they should - appear. - """ - return [] - - -class Group(MultiCommand): - """A group allows a command to have subcommands attached. This is the - most common way to implement nesting in Click. - - :param commands: a dictionary of commands. - """ - - def __init__(self, name=None, commands=None, **attrs): - MultiCommand.__init__(self, name, **attrs) - #: the registered subcommands by their exported names. - self.commands = commands or {} - - def add_command(self, cmd, name=None): - """Registers another :class:`Command` with this group. If the name - is not provided, the name of the command is used. - """ - name = name or cmd.name - if name is None: - raise TypeError("Command has no name.") - _check_multicommand(self, name, cmd, register=True) - self.commands[name] = cmd - - def command(self, *args, **kwargs): - """A shortcut decorator for declaring and attaching a command to - the group. This takes the same arguments as :func:`command` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. - """ - from .decorators import command - - def decorator(f): - cmd = command(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - return decorator - - def group(self, *args, **kwargs): - """A shortcut decorator for declaring and attaching a group to - the group. This takes the same arguments as :func:`group` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. - """ - from .decorators import group - - def decorator(f): - cmd = group(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - return decorator - - def get_command(self, ctx, cmd_name): - return self.commands.get(cmd_name) - - def list_commands(self, ctx): - return sorted(self.commands) - - -class CommandCollection(MultiCommand): - """A command collection is a multi command that merges multiple multi - commands together into one. This is a straightforward implementation - that accepts a list of different multi commands as sources and - provides all the commands for each of them. - """ - - def __init__(self, name=None, sources=None, **attrs): - MultiCommand.__init__(self, name, **attrs) - #: The list of registered multi commands. - self.sources = sources or [] - - def add_source(self, multi_cmd): - """Adds a new multi command to the chain dispatcher.""" - self.sources.append(multi_cmd) - - def get_command(self, ctx, cmd_name): - for source in self.sources: - rv = source.get_command(ctx, cmd_name) - if rv is not None: - if self.chain: - _check_multicommand(self, cmd_name, rv) - return rv - - def list_commands(self, ctx): - rv = set() - for source in self.sources: - rv.update(source.list_commands(ctx)) - return sorted(rv) - - -class Parameter(object): - r"""A parameter to a command comes in two versions: they are either - :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently - not supported by design as some of the internals for parsing are - intentionally not finalized. - - Some settings are supported by both options and arguments. - - :param param_decls: the parameter declarations for this option or - argument. This is a list of flags or argument - names. - :param type: the type that should be used. Either a :class:`ParamType` - or a Python type. The later is converted into the former - automatically if supported. - :param required: controls if this is optional or not. - :param default: the default value if omitted. This can also be a callable, - in which case it's invoked when the default is needed - without any arguments. - :param callback: a callback that should be executed after the parameter - was matched. This is called as ``fn(ctx, param, - value)`` and needs to return the value. - :param nargs: the number of arguments to match. If not ``1`` the return - value is a tuple instead of single value. The default for - nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). - :param metavar: how the value is represented in the help page. - :param expose_value: if this is `True` then the value is passed onwards - to the command callback and stored on the context, - otherwise it's skipped. - :param is_eager: eager values are processed before non eager ones. This - should not be set for arguments or it will inverse the - order of processing. - :param envvar: a string or list of strings that are environment variables - that should be checked. - - .. versionchanged:: 7.1 - Empty environment variables are ignored rather than taking the - empty string value. This makes it possible for scripts to clear - variables if they can't unset them. - - .. versionchanged:: 2.0 - Changed signature for parameter callback to also be passed the - parameter. The old callback format will still work, but it will - raise a warning to give you a chance to migrate the code easier. - """ - param_type_name = "parameter" - - def __init__( - self, - param_decls=None, - type=None, - required=False, - default=None, - callback=None, - nargs=None, - metavar=None, - expose_value=True, - is_eager=False, - envvar=None, - autocompletion=None, - ): - self.name, self.opts, self.secondary_opts = self._parse_decls( - param_decls or (), expose_value - ) - - self.type = convert_type(type, default) - - # Default nargs to what the type tells us if we have that - # information available. - if nargs is None: - if self.type.is_composite: - nargs = self.type.arity - else: - nargs = 1 - - self.required = required - self.callback = callback - self.nargs = nargs - self.multiple = False - self.expose_value = expose_value - self.default = default - self.is_eager = is_eager - self.metavar = metavar - self.envvar = envvar - self.autocompletion = autocompletion - - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, self.name) - - @property - def human_readable_name(self): - """Returns the human readable name of this parameter. This is the - same as the name for options, but the metavar for arguments. - """ - return self.name - - def make_metavar(self): - if self.metavar is not None: - return self.metavar - metavar = self.type.get_metavar(self) - if metavar is None: - metavar = self.type.name.upper() - if self.nargs != 1: - metavar += "..." - return metavar - - def get_default(self, ctx): - """Given a context variable this calculates the default value.""" - # Otherwise go with the regular default. - if callable(self.default): - rv = self.default() - else: - rv = self.default - return self.type_cast_value(ctx, rv) - - def add_to_parser(self, parser, ctx): - pass - - def consume_value(self, ctx, opts): - value = opts.get(self.name) - if value is None: - value = self.value_from_envvar(ctx) - if value is None: - value = ctx.lookup_default(self.name) - return value - - def type_cast_value(self, ctx, value): - """Given a value this runs it properly through the type system. - This automatically handles things like `nargs` and `multiple` as - well as composite types. - """ - if self.type.is_composite: - if self.nargs <= 1: - raise TypeError( - "Attempted to invoke composite type but nargs has" - " been set to {}. This is not supported; nargs" - " needs to be set to a fixed value > 1.".format(self.nargs) - ) - if self.multiple: - return tuple(self.type(x or (), self, ctx) for x in value or ()) - return self.type(value or (), self, ctx) - - def _convert(value, level): - if level == 0: - return self.type(value, self, ctx) - return tuple(_convert(x, level - 1) for x in value or ()) - - return _convert(value, (self.nargs != 1) + bool(self.multiple)) - - def process_value(self, ctx, value): - """Given a value and context this runs the logic to convert the - value as necessary. - """ - # If the value we were given is None we do nothing. This way - # code that calls this can easily figure out if something was - # not provided. Otherwise it would be converted into an empty - # tuple for multiple invocations which is inconvenient. - if value is not None: - return self.type_cast_value(ctx, value) - - def value_is_missing(self, value): - if value is None: - return True - if (self.nargs != 1 or self.multiple) and value == (): - return True - return False - - def full_process_value(self, ctx, value): - value = self.process_value(ctx, value) - - if value is None and not ctx.resilient_parsing: - value = self.get_default(ctx) - - if self.required and self.value_is_missing(value): - raise MissingParameter(ctx=ctx, param=self) - - return value - - def resolve_envvar_value(self, ctx): - if self.envvar is None: - return - if isinstance(self.envvar, (tuple, list)): - for envvar in self.envvar: - rv = os.environ.get(envvar) - if rv is not None: - return rv - else: - rv = os.environ.get(self.envvar) - - if rv != "": - return rv - - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) - if rv is not None and self.nargs != 1: - rv = self.type.split_envvar_value(rv) - return rv - - def handle_parse_result(self, ctx, opts, args): - with augment_usage_errors(ctx, param=self): - value = self.consume_value(ctx, opts) - try: - value = self.full_process_value(ctx, value) - except Exception: - if not ctx.resilient_parsing: - raise - value = None - if self.callback is not None: - try: - value = invoke_param_callback(self.callback, ctx, self, value) - except Exception: - if not ctx.resilient_parsing: - raise - - if self.expose_value: - ctx.params[self.name] = value - return value, args - - def get_help_record(self, ctx): - pass - - def get_usage_pieces(self, ctx): - return [] - - def get_error_hint(self, ctx): - """Get a stringified version of the param for use in error messages to - indicate which param caused the error. - """ - hint_list = self.opts or [self.human_readable_name] - return " / ".join(repr(x) for x in hint_list) - - -class Option(Parameter): - """Options are usually optional values on the command line and - have some extra features that arguments don't have. - - All other parameters are passed onwards to the parameter constructor. - - :param show_default: controls if the default value should be shown on the - help page. Normally, defaults are not shown. If this - value is a string, it shows the string instead of the - value. This is particularly useful for dynamic options. - :param show_envvar: controls if an environment variable should be shown on - the help page. Normally, environment variables - are not shown. - :param prompt: if set to `True` or a non empty string then the user will be - prompted for input. If set to `True` the prompt will be the - option name capitalized. - :param confirmation_prompt: if set then the value will need to be confirmed - if it was prompted for. - :param hide_input: if this is `True` then the input on the prompt will be - hidden from the user. This is useful for password - input. - :param is_flag: forces this option to act as a flag. The default is - auto detection. - :param flag_value: which value should be used for this flag if it's - enabled. This is set to a boolean automatically if - the option string contains a slash to mark two options. - :param multiple: if this is set to `True` then the argument is accepted - multiple times and recorded. This is similar to ``nargs`` - in how it works but supports arbitrary number of - arguments. - :param count: this flag makes an option increment an integer. - :param allow_from_autoenv: if this is enabled then the value of this - parameter will be pulled from an environment - variable in case a prefix is defined on the - context. - :param help: the help string. - :param hidden: hide this option from help outputs. - """ - - param_type_name = "option" - - def __init__( - self, - param_decls=None, - show_default=False, - prompt=False, - confirmation_prompt=False, - hide_input=False, - is_flag=None, - flag_value=None, - multiple=False, - count=False, - allow_from_autoenv=True, - type=None, - help=None, - hidden=False, - show_choices=True, - show_envvar=False, - **attrs - ): - default_is_missing = attrs.get("default", _missing) is _missing - Parameter.__init__(self, param_decls, type=type, **attrs) - - if prompt is True: - prompt_text = self.name.replace("_", " ").capitalize() - elif prompt is False: - prompt_text = None - else: - prompt_text = prompt - self.prompt = prompt_text - self.confirmation_prompt = confirmation_prompt - self.hide_input = hide_input - self.hidden = hidden - - # Flags - if is_flag is None: - if flag_value is not None: - is_flag = True - else: - is_flag = bool(self.secondary_opts) - if is_flag and default_is_missing: - self.default = False - if flag_value is None: - flag_value = not self.default - self.is_flag = is_flag - self.flag_value = flag_value - if self.is_flag and isinstance(self.flag_value, bool) and type in [None, bool]: - self.type = BOOL - self.is_bool_flag = True - else: - self.is_bool_flag = False - - # Counting - self.count = count - if count: - if type is None: - self.type = IntRange(min=0) - if default_is_missing: - self.default = 0 - - self.multiple = multiple - self.allow_from_autoenv = allow_from_autoenv - self.help = help - self.show_default = show_default - self.show_choices = show_choices - self.show_envvar = show_envvar - - # Sanity check for stuff we don't support - if __debug__: - if self.nargs < 0: - raise TypeError("Options cannot have nargs < 0") - if self.prompt and self.is_flag and not self.is_bool_flag: - raise TypeError("Cannot prompt for flags that are not bools.") - if not self.is_bool_flag and self.secondary_opts: - raise TypeError("Got secondary option for non boolean flag.") - if self.is_bool_flag and self.hide_input and self.prompt is not None: - raise TypeError("Hidden input does not work with boolean flag prompts.") - if self.count: - if self.multiple: - raise TypeError( - "Options cannot be multiple and count at the same time." - ) - elif self.is_flag: - raise TypeError( - "Options cannot be count and flags at the same time." - ) - - def _parse_decls(self, decls, expose_value): - opts = [] - secondary_opts = [] - name = None - possible_names = [] - - for decl in decls: - if isidentifier(decl): - if name is not None: - raise TypeError("Name defined twice") - name = decl - else: - split_char = ";" if decl[:1] == "/" else "/" - if split_char in decl: - first, second = decl.split(split_char, 1) - first = first.rstrip() - if first: - possible_names.append(split_opt(first)) - opts.append(first) - second = second.lstrip() - if second: - secondary_opts.append(second.lstrip()) - else: - possible_names.append(split_opt(decl)) - opts.append(decl) - - if name is None and possible_names: - possible_names.sort(key=lambda x: -len(x[0])) # group long options first - name = possible_names[0][1].replace("-", "_").lower() - if not isidentifier(name): - name = None - - if name is None: - if not expose_value: - return None, opts, secondary_opts - raise TypeError("Could not determine name for option") - - if not opts and not secondary_opts: - raise TypeError( - "No options defined but a name was passed ({}). Did you" - " mean to declare an argument instead of an option?".format(name) - ) - - return name, opts, secondary_opts - - def add_to_parser(self, parser, ctx): - kwargs = { - "dest": self.name, - "nargs": self.nargs, - "obj": self, - } - - if self.multiple: - action = "append" - elif self.count: - action = "count" - else: - action = "store" - - if self.is_flag: - kwargs.pop("nargs", None) - action_const = "{}_const".format(action) - if self.is_bool_flag and self.secondary_opts: - parser.add_option(self.opts, action=action_const, const=True, **kwargs) - parser.add_option( - self.secondary_opts, action=action_const, const=False, **kwargs - ) - else: - parser.add_option( - self.opts, action=action_const, const=self.flag_value, **kwargs - ) - else: - kwargs["action"] = action - parser.add_option(self.opts, **kwargs) - - def get_help_record(self, ctx): - if self.hidden: - return - any_prefix_is_slash = [] - - def _write_opts(opts): - rv, any_slashes = join_options(opts) - if any_slashes: - any_prefix_is_slash[:] = [True] - if not self.is_flag and not self.count: - rv += " {}".format(self.make_metavar()) - return rv - - rv = [_write_opts(self.opts)] - if self.secondary_opts: - rv.append(_write_opts(self.secondary_opts)) - - help = self.help or "" - extra = [] - if self.show_envvar: - envvar = self.envvar - if envvar is None: - if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None: - envvar = "{}_{}".format(ctx.auto_envvar_prefix, self.name.upper()) - if envvar is not None: - extra.append( - "env var: {}".format( - ", ".join(str(d) for d in envvar) - if isinstance(envvar, (list, tuple)) - else envvar - ) - ) - if self.default is not None and (self.show_default or ctx.show_default): - if isinstance(self.show_default, string_types): - default_string = "({})".format(self.show_default) - elif isinstance(self.default, (list, tuple)): - default_string = ", ".join(str(d) for d in self.default) - elif inspect.isfunction(self.default): - default_string = "(dynamic)" - else: - default_string = self.default - extra.append("default: {}".format(default_string)) - - if self.required: - extra.append("required") - if extra: - help = "{}[{}]".format( - "{} ".format(help) if help else "", "; ".join(extra) - ) - - return ("; " if any_prefix_is_slash else " / ").join(rv), help - - def get_default(self, ctx): - # If we're a non boolean flag our default is more complex because - # we need to look at all flags in the same group to figure out - # if we're the the default one in which case we return the flag - # value as default. - if self.is_flag and not self.is_bool_flag: - for param in ctx.command.params: - if param.name == self.name and param.default: - return param.flag_value - return None - return Parameter.get_default(self, ctx) - - def prompt_for_value(self, ctx): - """This is an alternative flow that can be activated in the full - value processing if a value does not exist. It will prompt the - user until a valid value exists and then returns the processed - value as result. - """ - # Calculate the default before prompting anything to be stable. - default = self.get_default(ctx) - - # If this is a prompt for a flag we need to handle this - # differently. - if self.is_bool_flag: - return confirm(self.prompt, default) - - return prompt( - self.prompt, - default=default, - type=self.type, - hide_input=self.hide_input, - show_choices=self.show_choices, - confirmation_prompt=self.confirmation_prompt, - value_proc=lambda x: self.process_value(ctx, x), - ) - - def resolve_envvar_value(self, ctx): - rv = Parameter.resolve_envvar_value(self, ctx) - if rv is not None: - return rv - if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None: - envvar = "{}_{}".format(ctx.auto_envvar_prefix, self.name.upper()) - return os.environ.get(envvar) - - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) - if rv is None: - return None - value_depth = (self.nargs != 1) + bool(self.multiple) - if value_depth > 0 and rv is not None: - rv = self.type.split_envvar_value(rv) - if self.multiple and self.nargs != 1: - rv = batch(rv, self.nargs) - return rv - - def full_process_value(self, ctx, value): - if value is None and self.prompt is not None and not ctx.resilient_parsing: - return self.prompt_for_value(ctx) - return Parameter.full_process_value(self, ctx, value) - - -class Argument(Parameter): - """Arguments are positional parameters to a command. They generally - provide fewer features than options but can have infinite ``nargs`` - and are required by default. - - All parameters are passed onwards to the parameter constructor. - """ - - param_type_name = "argument" - - def __init__(self, param_decls, required=None, **attrs): - if required is None: - if attrs.get("default") is not None: - required = False - else: - required = attrs.get("nargs", 1) > 0 - Parameter.__init__(self, param_decls, required=required, **attrs) - if self.default is not None and self.nargs < 0: - raise TypeError( - "nargs=-1 in combination with a default value is not supported." - ) - - @property - def human_readable_name(self): - if self.metavar is not None: - return self.metavar - return self.name.upper() - - def make_metavar(self): - if self.metavar is not None: - return self.metavar - var = self.type.get_metavar(self) - if not var: - var = self.name.upper() - if not self.required: - var = "[{}]".format(var) - if self.nargs != 1: - var += "..." - return var - - def _parse_decls(self, decls, expose_value): - if not decls: - if not expose_value: - return None, [], [] - raise TypeError("Could not determine name for argument") - if len(decls) == 1: - name = arg = decls[0] - name = name.replace("-", "_").lower() - else: - raise TypeError( - "Arguments take exactly one parameter declaration, got" - " {}".format(len(decls)) - ) - return name, [arg], [] - - def get_usage_pieces(self, ctx): - return [self.make_metavar()] - - def get_error_hint(self, ctx): - return repr(self.make_metavar()) - - def add_to_parser(self, parser, ctx): - parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/decorators.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/decorators.py deleted file mode 100644 index c7b5af6..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/decorators.py +++ /dev/null @@ -1,333 +0,0 @@ -import inspect -import sys -from functools import update_wrapper - -from ._compat import iteritems -from ._unicodefun import _check_for_unicode_literals -from .core import Argument -from .core import Command -from .core import Group -from .core import Option -from .globals import get_current_context -from .utils import echo - - -def pass_context(f): - """Marks a callback as wanting to receive the current context - object as first argument. - """ - - def new_func(*args, **kwargs): - return f(get_current_context(), *args, **kwargs) - - return update_wrapper(new_func, f) - - -def pass_obj(f): - """Similar to :func:`pass_context`, but only pass the object on the - context onwards (:attr:`Context.obj`). This is useful if that object - represents the state of a nested system. - """ - - def new_func(*args, **kwargs): - return f(get_current_context().obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - -def make_pass_decorator(object_type, ensure=False): - """Given an object type this creates a decorator that will work - similar to :func:`pass_obj` but instead of passing the object of the - current context, it will find the innermost context of type - :func:`object_type`. - - This generates a decorator that works roughly like this:: - - from functools import update_wrapper - - def decorator(f): - @pass_context - def new_func(ctx, *args, **kwargs): - obj = ctx.find_object(object_type) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - :param object_type: the type of the object to pass. - :param ensure: if set to `True`, a new object will be created and - remembered on the context if it's not there yet. - """ - - def decorator(f): - def new_func(*args, **kwargs): - ctx = get_current_context() - if ensure: - obj = ctx.ensure_object(object_type) - else: - obj = ctx.find_object(object_type) - if obj is None: - raise RuntimeError( - "Managed to invoke callback without a context" - " object of type '{}' existing".format(object_type.__name__) - ) - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - return decorator - - -def _make_command(f, name, attrs, cls): - if isinstance(f, Command): - raise TypeError("Attempted to convert a callback into a command twice.") - try: - params = f.__click_params__ - params.reverse() - del f.__click_params__ - except AttributeError: - params = [] - help = attrs.get("help") - if help is None: - help = inspect.getdoc(f) - if isinstance(help, bytes): - help = help.decode("utf-8") - else: - help = inspect.cleandoc(help) - attrs["help"] = help - _check_for_unicode_literals() - return cls( - name=name or f.__name__.lower().replace("_", "-"), - callback=f, - params=params, - **attrs - ) - - -def command(name=None, cls=None, **attrs): - r"""Creates a new :class:`Command` and uses the decorated function as - callback. This will also automatically attach all decorated - :func:`option`\s and :func:`argument`\s as parameters to the command. - - The name of the command defaults to the name of the function with - underscores replaced by dashes. If you want to change that, you can - pass the intended name as the first argument. - - All keyword arguments are forwarded to the underlying command class. - - Once decorated the function turns into a :class:`Command` instance - that can be invoked as a command line utility or be attached to a - command :class:`Group`. - - :param name: the name of the command. This defaults to the function - name with underscores replaced by dashes. - :param cls: the command class to instantiate. This defaults to - :class:`Command`. - """ - if cls is None: - cls = Command - - def decorator(f): - cmd = _make_command(f, name, attrs, cls) - cmd.__doc__ = f.__doc__ - return cmd - - return decorator - - -def group(name=None, **attrs): - """Creates a new :class:`Group` with a function as callback. This - works otherwise the same as :func:`command` just that the `cls` - parameter is set to :class:`Group`. - """ - attrs.setdefault("cls", Group) - return command(name, **attrs) - - -def _param_memo(f, param): - if isinstance(f, Command): - f.params.append(param) - else: - if not hasattr(f, "__click_params__"): - f.__click_params__ = [] - f.__click_params__.append(param) - - -def argument(*param_decls, **attrs): - """Attaches an argument to the command. All positional arguments are - passed as parameter declarations to :class:`Argument`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Argument` instance manually - and attaching it to the :attr:`Command.params` list. - - :param cls: the argument class to instantiate. This defaults to - :class:`Argument`. - """ - - def decorator(f): - ArgumentClass = attrs.pop("cls", Argument) - _param_memo(f, ArgumentClass(param_decls, **attrs)) - return f - - return decorator - - -def option(*param_decls, **attrs): - """Attaches an option to the command. All positional arguments are - passed as parameter declarations to :class:`Option`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Option` instance manually - and attaching it to the :attr:`Command.params` list. - - :param cls: the option class to instantiate. This defaults to - :class:`Option`. - """ - - def decorator(f): - # Issue 926, copy attrs, so pre-defined options can re-use the same cls= - option_attrs = attrs.copy() - - if "help" in option_attrs: - option_attrs["help"] = inspect.cleandoc(option_attrs["help"]) - OptionClass = option_attrs.pop("cls", Option) - _param_memo(f, OptionClass(param_decls, **option_attrs)) - return f - - return decorator - - -def confirmation_option(*param_decls, **attrs): - """Shortcut for confirmation prompts that can be ignored by passing - ``--yes`` as parameter. - - This is equivalent to decorating a function with :func:`option` with - the following parameters:: - - def callback(ctx, param, value): - if not value: - ctx.abort() - - @click.command() - @click.option('--yes', is_flag=True, callback=callback, - expose_value=False, prompt='Do you want to continue?') - def dropdb(): - pass - """ - - def decorator(f): - def callback(ctx, param, value): - if not value: - ctx.abort() - - attrs.setdefault("is_flag", True) - attrs.setdefault("callback", callback) - attrs.setdefault("expose_value", False) - attrs.setdefault("prompt", "Do you want to continue?") - attrs.setdefault("help", "Confirm the action without prompting.") - return option(*(param_decls or ("--yes",)), **attrs)(f) - - return decorator - - -def password_option(*param_decls, **attrs): - """Shortcut for password prompts. - - This is equivalent to decorating a function with :func:`option` with - the following parameters:: - - @click.command() - @click.option('--password', prompt=True, confirmation_prompt=True, - hide_input=True) - def changeadmin(password): - pass - """ - - def decorator(f): - attrs.setdefault("prompt", True) - attrs.setdefault("confirmation_prompt", True) - attrs.setdefault("hide_input", True) - return option(*(param_decls or ("--password",)), **attrs)(f) - - return decorator - - -def version_option(version=None, *param_decls, **attrs): - """Adds a ``--version`` option which immediately ends the program - printing out the version number. This is implemented as an eager - option that prints the version and exits the program in the callback. - - :param version: the version number to show. If not provided Click - attempts an auto discovery via setuptools. - :param prog_name: the name of the program (defaults to autodetection) - :param message: custom message to show instead of the default - (``'%(prog)s, version %(version)s'``) - :param others: everything else is forwarded to :func:`option`. - """ - if version is None: - if hasattr(sys, "_getframe"): - module = sys._getframe(1).f_globals.get("__name__") - else: - module = "" - - def decorator(f): - prog_name = attrs.pop("prog_name", None) - message = attrs.pop("message", "%(prog)s, version %(version)s") - - def callback(ctx, param, value): - if not value or ctx.resilient_parsing: - return - prog = prog_name - if prog is None: - prog = ctx.find_root().info_name - ver = version - if ver is None: - try: - import pkg_resources - except ImportError: - pass - else: - for dist in pkg_resources.working_set: - scripts = dist.get_entry_map().get("console_scripts") or {} - for _, entry_point in iteritems(scripts): - if entry_point.module_name == module: - ver = dist.version - break - if ver is None: - raise RuntimeError("Could not determine version") - echo(message % {"prog": prog, "version": ver}, color=ctx.color) - ctx.exit() - - attrs.setdefault("is_flag", True) - attrs.setdefault("expose_value", False) - attrs.setdefault("is_eager", True) - attrs.setdefault("help", "Show the version and exit.") - attrs["callback"] = callback - return option(*(param_decls or ("--version",)), **attrs)(f) - - return decorator - - -def help_option(*param_decls, **attrs): - """Adds a ``--help`` option which immediately ends the program - printing out the help page. This is usually unnecessary to add as - this is added by default to all commands unless suppressed. - - Like :func:`version_option`, this is implemented as eager option that - prints in the callback and exits. - - All arguments are forwarded to :func:`option`. - """ - - def decorator(f): - def callback(ctx, param, value): - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - attrs.setdefault("is_flag", True) - attrs.setdefault("expose_value", False) - attrs.setdefault("help", "Show this message and exit.") - attrs.setdefault("is_eager", True) - attrs["callback"] = callback - return option(*(param_decls or ("--help",)), **attrs)(f) - - return decorator diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/exceptions.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/exceptions.py deleted file mode 100644 index 592ee38..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/exceptions.py +++ /dev/null @@ -1,253 +0,0 @@ -from ._compat import filename_to_ui -from ._compat import get_text_stderr -from ._compat import PY2 -from .utils import echo - - -def _join_param_hints(param_hint): - if isinstance(param_hint, (tuple, list)): - return " / ".join(repr(x) for x in param_hint) - return param_hint - - -class ClickException(Exception): - """An exception that Click can handle and show to the user.""" - - #: The exit code for this exception - exit_code = 1 - - def __init__(self, message): - ctor_msg = message - if PY2: - if ctor_msg is not None: - ctor_msg = ctor_msg.encode("utf-8") - Exception.__init__(self, ctor_msg) - self.message = message - - def format_message(self): - return self.message - - def __str__(self): - return self.message - - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.message.encode("utf-8") - - def show(self, file=None): - if file is None: - file = get_text_stderr() - echo("Error: {}".format(self.format_message()), file=file) - - -class UsageError(ClickException): - """An internal exception that signals a usage error. This typically - aborts any further handling. - - :param message: the error message to display. - :param ctx: optionally the context that caused this error. Click will - fill in the context automatically in some situations. - """ - - exit_code = 2 - - def __init__(self, message, ctx=None): - ClickException.__init__(self, message) - self.ctx = ctx - self.cmd = self.ctx.command if self.ctx else None - - def show(self, file=None): - if file is None: - file = get_text_stderr() - color = None - hint = "" - if self.cmd is not None and self.cmd.get_help_option(self.ctx) is not None: - hint = "Try '{} {}' for help.\n".format( - self.ctx.command_path, self.ctx.help_option_names[0] - ) - if self.ctx is not None: - color = self.ctx.color - echo("{}\n{}".format(self.ctx.get_usage(), hint), file=file, color=color) - echo("Error: {}".format(self.format_message()), file=file, color=color) - - -class BadParameter(UsageError): - """An exception that formats out a standardized error message for a - bad parameter. This is useful when thrown from a callback or type as - Click will attach contextual information to it (for instance, which - parameter it is). - - .. versionadded:: 2.0 - - :param param: the parameter object that caused this error. This can - be left out, and Click will attach this info itself - if possible. - :param param_hint: a string that shows up as parameter name. This - can be used as alternative to `param` in cases - where custom validation should happen. If it is - a string it's used as such, if it's a list then - each item is quoted and separated. - """ - - def __init__(self, message, ctx=None, param=None, param_hint=None): - UsageError.__init__(self, message, ctx) - self.param = param - self.param_hint = param_hint - - def format_message(self): - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - return "Invalid value: {}".format(self.message) - param_hint = _join_param_hints(param_hint) - - return "Invalid value for {}: {}".format(param_hint, self.message) - - -class MissingParameter(BadParameter): - """Raised if click required an option or argument but it was not - provided when invoking the script. - - .. versionadded:: 4.0 - - :param param_type: a string that indicates the type of the parameter. - The default is to inherit the parameter type from - the given `param`. Valid values are ``'parameter'``, - ``'option'`` or ``'argument'``. - """ - - def __init__( - self, message=None, ctx=None, param=None, param_hint=None, param_type=None - ): - BadParameter.__init__(self, message, ctx, param, param_hint) - self.param_type = param_type - - def format_message(self): - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - param_hint = None - param_hint = _join_param_hints(param_hint) - - param_type = self.param_type - if param_type is None and self.param is not None: - param_type = self.param.param_type_name - - msg = self.message - if self.param is not None: - msg_extra = self.param.type.get_missing_message(self.param) - if msg_extra: - if msg: - msg += ". {}".format(msg_extra) - else: - msg = msg_extra - - return "Missing {}{}{}{}".format( - param_type, - " {}".format(param_hint) if param_hint else "", - ". " if msg else ".", - msg or "", - ) - - def __str__(self): - if self.message is None: - param_name = self.param.name if self.param else None - return "missing parameter: {}".format(param_name) - else: - return self.message - - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.__unicode__().encode("utf-8") - - -class NoSuchOption(UsageError): - """Raised if click attempted to handle an option that does not - exist. - - .. versionadded:: 4.0 - """ - - def __init__(self, option_name, message=None, possibilities=None, ctx=None): - if message is None: - message = "no such option: {}".format(option_name) - UsageError.__init__(self, message, ctx) - self.option_name = option_name - self.possibilities = possibilities - - def format_message(self): - bits = [self.message] - if self.possibilities: - if len(self.possibilities) == 1: - bits.append("Did you mean {}?".format(self.possibilities[0])) - else: - possibilities = sorted(self.possibilities) - bits.append("(Possible options: {})".format(", ".join(possibilities))) - return " ".join(bits) - - -class BadOptionUsage(UsageError): - """Raised if an option is generally supplied but the use of the option - was incorrect. This is for instance raised if the number of arguments - for an option is not correct. - - .. versionadded:: 4.0 - - :param option_name: the name of the option being used incorrectly. - """ - - def __init__(self, option_name, message, ctx=None): - UsageError.__init__(self, message, ctx) - self.option_name = option_name - - -class BadArgumentUsage(UsageError): - """Raised if an argument is generally supplied but the use of the argument - was incorrect. This is for instance raised if the number of values - for an argument is not correct. - - .. versionadded:: 6.0 - """ - - def __init__(self, message, ctx=None): - UsageError.__init__(self, message, ctx) - - -class FileError(ClickException): - """Raised if a file cannot be opened.""" - - def __init__(self, filename, hint=None): - ui_filename = filename_to_ui(filename) - if hint is None: - hint = "unknown error" - ClickException.__init__(self, hint) - self.ui_filename = ui_filename - self.filename = filename - - def format_message(self): - return "Could not open file {}: {}".format(self.ui_filename, self.message) - - -class Abort(RuntimeError): - """An internal signalling exception that signals Click to abort.""" - - -class Exit(RuntimeError): - """An exception that indicates that the application should exit with some - status code. - - :param code: the status code to exit with. - """ - - __slots__ = ("exit_code",) - - def __init__(self, code=0): - self.exit_code = code diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/formatting.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/formatting.py deleted file mode 100644 index 319c7f6..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/formatting.py +++ /dev/null @@ -1,283 +0,0 @@ -from contextlib import contextmanager - -from ._compat import term_len -from .parser import split_opt -from .termui import get_terminal_size - -# Can force a width. This is used by the test system -FORCED_WIDTH = None - - -def measure_table(rows): - widths = {} - for row in rows: - for idx, col in enumerate(row): - widths[idx] = max(widths.get(idx, 0), term_len(col)) - return tuple(y for x, y in sorted(widths.items())) - - -def iter_rows(rows, col_count): - for row in rows: - row = tuple(row) - yield row + ("",) * (col_count - len(row)) - - -def wrap_text( - text, width=78, initial_indent="", subsequent_indent="", preserve_paragraphs=False -): - """A helper function that intelligently wraps text. By default, it - assumes that it operates on a single paragraph of text but if the - `preserve_paragraphs` parameter is provided it will intelligently - handle paragraphs (defined by two empty lines). - - If paragraphs are handled, a paragraph can be prefixed with an empty - line containing the ``\\b`` character (``\\x08``) to indicate that - no rewrapping should happen in that block. - - :param text: the text that should be rewrapped. - :param width: the maximum width for the text. - :param initial_indent: the initial indent that should be placed on the - first line as a string. - :param subsequent_indent: the indent string that should be placed on - each consecutive line. - :param preserve_paragraphs: if this flag is set then the wrapping will - intelligently handle paragraphs. - """ - from ._textwrap import TextWrapper - - text = text.expandtabs() - wrapper = TextWrapper( - width, - initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - replace_whitespace=False, - ) - if not preserve_paragraphs: - return wrapper.fill(text) - - p = [] - buf = [] - indent = None - - def _flush_par(): - if not buf: - return - if buf[0].strip() == "\b": - p.append((indent or 0, True, "\n".join(buf[1:]))) - else: - p.append((indent or 0, False, " ".join(buf))) - del buf[:] - - for line in text.splitlines(): - if not line: - _flush_par() - indent = None - else: - if indent is None: - orig_len = term_len(line) - line = line.lstrip() - indent = orig_len - term_len(line) - buf.append(line) - _flush_par() - - rv = [] - for indent, raw, text in p: - with wrapper.extra_indent(" " * indent): - if raw: - rv.append(wrapper.indent_only(text)) - else: - rv.append(wrapper.fill(text)) - - return "\n\n".join(rv) - - -class HelpFormatter(object): - """This class helps with formatting text-based help pages. It's - usually just needed for very special internal cases, but it's also - exposed so that developers can write their own fancy outputs. - - At present, it always writes into memory. - - :param indent_increment: the additional increment for each level. - :param width: the width for the text. This defaults to the terminal - width clamped to a maximum of 78. - """ - - def __init__(self, indent_increment=2, width=None, max_width=None): - self.indent_increment = indent_increment - if max_width is None: - max_width = 80 - if width is None: - width = FORCED_WIDTH - if width is None: - width = max(min(get_terminal_size()[0], max_width) - 2, 50) - self.width = width - self.current_indent = 0 - self.buffer = [] - - def write(self, string): - """Writes a unicode string into the internal buffer.""" - self.buffer.append(string) - - def indent(self): - """Increases the indentation.""" - self.current_indent += self.indent_increment - - def dedent(self): - """Decreases the indentation.""" - self.current_indent -= self.indent_increment - - def write_usage(self, prog, args="", prefix="Usage: "): - """Writes a usage line into the buffer. - - :param prog: the program name. - :param args: whitespace separated list of arguments. - :param prefix: the prefix for the first line. - """ - usage_prefix = "{:>{w}}{} ".format(prefix, prog, w=self.current_indent) - text_width = self.width - self.current_indent - - if text_width >= (term_len(usage_prefix) + 20): - # The arguments will fit to the right of the prefix. - indent = " " * term_len(usage_prefix) - self.write( - wrap_text( - args, - text_width, - initial_indent=usage_prefix, - subsequent_indent=indent, - ) - ) - else: - # The prefix is too long, put the arguments on the next line. - self.write(usage_prefix) - self.write("\n") - indent = " " * (max(self.current_indent, term_len(prefix)) + 4) - self.write( - wrap_text( - args, text_width, initial_indent=indent, subsequent_indent=indent - ) - ) - - self.write("\n") - - def write_heading(self, heading): - """Writes a heading into the buffer.""" - self.write("{:>{w}}{}:\n".format("", heading, w=self.current_indent)) - - def write_paragraph(self): - """Writes a paragraph into the buffer.""" - if self.buffer: - self.write("\n") - - def write_text(self, text): - """Writes re-indented text into the buffer. This rewraps and - preserves paragraphs. - """ - text_width = max(self.width - self.current_indent, 11) - indent = " " * self.current_indent - self.write( - wrap_text( - text, - text_width, - initial_indent=indent, - subsequent_indent=indent, - preserve_paragraphs=True, - ) - ) - self.write("\n") - - def write_dl(self, rows, col_max=30, col_spacing=2): - """Writes a definition list into the buffer. This is how options - and commands are usually formatted. - - :param rows: a list of two item tuples for the terms and values. - :param col_max: the maximum width of the first column. - :param col_spacing: the number of spaces between the first and - second column. - """ - rows = list(rows) - widths = measure_table(rows) - if len(widths) != 2: - raise TypeError("Expected two columns for definition list") - - first_col = min(widths[0], col_max) + col_spacing - - for first, second in iter_rows(rows, len(widths)): - self.write("{:>{w}}{}".format("", first, w=self.current_indent)) - if not second: - self.write("\n") - continue - if term_len(first) <= first_col - col_spacing: - self.write(" " * (first_col - term_len(first))) - else: - self.write("\n") - self.write(" " * (first_col + self.current_indent)) - - text_width = max(self.width - first_col - 2, 10) - wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) - lines = wrapped_text.splitlines() - - if lines: - self.write("{}\n".format(lines[0])) - - for line in lines[1:]: - self.write( - "{:>{w}}{}\n".format( - "", line, w=first_col + self.current_indent - ) - ) - - if len(lines) > 1: - # separate long help from next option - self.write("\n") - else: - self.write("\n") - - @contextmanager - def section(self, name): - """Helpful context manager that writes a paragraph, a heading, - and the indents. - - :param name: the section name that is written as heading. - """ - self.write_paragraph() - self.write_heading(name) - self.indent() - try: - yield - finally: - self.dedent() - - @contextmanager - def indentation(self): - """A context manager that increases the indentation.""" - self.indent() - try: - yield - finally: - self.dedent() - - def getvalue(self): - """Returns the buffer contents.""" - return "".join(self.buffer) - - -def join_options(options): - """Given a list of option strings this joins them in the most appropriate - way and returns them in the form ``(formatted_string, - any_prefix_is_slash)`` where the second item in the tuple is a flag that - indicates if any of the option prefixes was a slash. - """ - rv = [] - any_prefix_is_slash = False - for opt in options: - prefix = split_opt(opt)[0] - if prefix == "/": - any_prefix_is_slash = True - rv.append((len(prefix), opt)) - - rv.sort(key=lambda x: x[0]) - - rv = ", ".join(x[1] for x in rv) - return rv, any_prefix_is_slash diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/globals.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/globals.py deleted file mode 100644 index 1649f9a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/globals.py +++ /dev/null @@ -1,47 +0,0 @@ -from threading import local - -_local = local() - - -def get_current_context(silent=False): - """Returns the current click context. This can be used as a way to - access the current context object from anywhere. This is a more implicit - alternative to the :func:`pass_context` decorator. This function is - primarily useful for helpers such as :func:`echo` which might be - interested in changing its behavior based on the current context. - - To push the current context, :meth:`Context.scope` can be used. - - .. versionadded:: 5.0 - - :param silent: if set to `True` the return value is `None` if no context - is available. The default behavior is to raise a - :exc:`RuntimeError`. - """ - try: - return _local.stack[-1] - except (AttributeError, IndexError): - if not silent: - raise RuntimeError("There is no active click context.") - - -def push_context(ctx): - """Pushes a new context to the current stack.""" - _local.__dict__.setdefault("stack", []).append(ctx) - - -def pop_context(): - """Removes the top level from the stack.""" - _local.stack.pop() - - -def resolve_color_default(color=None): - """"Internal helper to get the default value of the color flag. If a - value is passed it's returned unchanged, otherwise it's looked up from - the current context. - """ - if color is not None: - return color - ctx = get_current_context(silent=True) - if ctx is not None: - return ctx.color diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/parser.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/parser.py deleted file mode 100644 index f43ebfe..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/parser.py +++ /dev/null @@ -1,428 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module started out as largely a copy paste from the stdlib's -optparse module with the features removed that we do not need from -optparse because we implement them in Click on a higher level (for -instance type handling, help formatting and a lot more). - -The plan is to remove more and more from here over time. - -The reason this is a different module and not optparse from the stdlib -is that there are differences in 2.x and 3.x about the error messages -generated and optparse in the stdlib uses gettext for no good reason -and might cause us issues. - -Click uses parts of optparse written by Gregory P. Ward and maintained -by the Python Software Foundation. This is limited to code in parser.py. - -Copyright 2001-2006 Gregory P. Ward. All rights reserved. -Copyright 2002-2006 Python Software Foundation. All rights reserved. -""" -import re -from collections import deque - -from .exceptions import BadArgumentUsage -from .exceptions import BadOptionUsage -from .exceptions import NoSuchOption -from .exceptions import UsageError - - -def _unpack_args(args, nargs_spec): - """Given an iterable of arguments and an iterable of nargs specifications, - it returns a tuple with all the unpacked arguments at the first index - and all remaining arguments as the second. - - The nargs specification is the number of arguments that should be consumed - or `-1` to indicate that this position should eat up all the remainders. - - Missing items are filled with `None`. - """ - args = deque(args) - nargs_spec = deque(nargs_spec) - rv = [] - spos = None - - def _fetch(c): - try: - if spos is None: - return c.popleft() - else: - return c.pop() - except IndexError: - return None - - while nargs_spec: - nargs = _fetch(nargs_spec) - if nargs == 1: - rv.append(_fetch(args)) - elif nargs > 1: - x = [_fetch(args) for _ in range(nargs)] - # If we're reversed, we're pulling in the arguments in reverse, - # so we need to turn them around. - if spos is not None: - x.reverse() - rv.append(tuple(x)) - elif nargs < 0: - if spos is not None: - raise TypeError("Cannot have two nargs < 0") - spos = len(rv) - rv.append(None) - - # spos is the position of the wildcard (star). If it's not `None`, - # we fill it with the remainder. - if spos is not None: - rv[spos] = tuple(args) - args = [] - rv[spos + 1 :] = reversed(rv[spos + 1 :]) - - return tuple(rv), list(args) - - -def _error_opt_args(nargs, opt): - if nargs == 1: - raise BadOptionUsage(opt, "{} option requires an argument".format(opt)) - raise BadOptionUsage(opt, "{} option requires {} arguments".format(opt, nargs)) - - -def split_opt(opt): - first = opt[:1] - if first.isalnum(): - return "", opt - if opt[1:2] == first: - return opt[:2], opt[2:] - return first, opt[1:] - - -def normalize_opt(opt, ctx): - if ctx is None or ctx.token_normalize_func is None: - return opt - prefix, opt = split_opt(opt) - return prefix + ctx.token_normalize_func(opt) - - -def split_arg_string(string): - """Given an argument string this attempts to split it into small parts.""" - rv = [] - for match in re.finditer( - r"('([^'\\]*(?:\\.[^'\\]*)*)'|\"([^\"\\]*(?:\\.[^\"\\]*)*)\"|\S+)\s*", - string, - re.S, - ): - arg = match.group().strip() - if arg[:1] == arg[-1:] and arg[:1] in "\"'": - arg = arg[1:-1].encode("ascii", "backslashreplace").decode("unicode-escape") - try: - arg = type(string)(arg) - except UnicodeError: - pass - rv.append(arg) - return rv - - -class Option(object): - def __init__(self, opts, dest, action=None, nargs=1, const=None, obj=None): - self._short_opts = [] - self._long_opts = [] - self.prefixes = set() - - for opt in opts: - prefix, value = split_opt(opt) - if not prefix: - raise ValueError("Invalid start character for option ({})".format(opt)) - self.prefixes.add(prefix[0]) - if len(prefix) == 1 and len(value) == 1: - self._short_opts.append(opt) - else: - self._long_opts.append(opt) - self.prefixes.add(prefix) - - if action is None: - action = "store" - - self.dest = dest - self.action = action - self.nargs = nargs - self.const = const - self.obj = obj - - @property - def takes_value(self): - return self.action in ("store", "append") - - def process(self, value, state): - if self.action == "store": - state.opts[self.dest] = value - elif self.action == "store_const": - state.opts[self.dest] = self.const - elif self.action == "append": - state.opts.setdefault(self.dest, []).append(value) - elif self.action == "append_const": - state.opts.setdefault(self.dest, []).append(self.const) - elif self.action == "count": - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 - else: - raise ValueError("unknown action '{}'".format(self.action)) - state.order.append(self.obj) - - -class Argument(object): - def __init__(self, dest, nargs=1, obj=None): - self.dest = dest - self.nargs = nargs - self.obj = obj - - def process(self, value, state): - if self.nargs > 1: - holes = sum(1 for x in value if x is None) - if holes == len(value): - value = None - elif holes != 0: - raise BadArgumentUsage( - "argument {} takes {} values".format(self.dest, self.nargs) - ) - state.opts[self.dest] = value - state.order.append(self.obj) - - -class ParsingState(object): - def __init__(self, rargs): - self.opts = {} - self.largs = [] - self.rargs = rargs - self.order = [] - - -class OptionParser(object): - """The option parser is an internal class that is ultimately used to - parse options and arguments. It's modelled after optparse and brings - a similar but vastly simplified API. It should generally not be used - directly as the high level Click classes wrap it for you. - - It's not nearly as extensible as optparse or argparse as it does not - implement features that are implemented on a higher level (such as - types or defaults). - - :param ctx: optionally the :class:`~click.Context` where this parser - should go with. - """ - - def __init__(self, ctx=None): - #: The :class:`~click.Context` for this parser. This might be - #: `None` for some advanced use cases. - self.ctx = ctx - #: This controls how the parser deals with interspersed arguments. - #: If this is set to `False`, the parser will stop on the first - #: non-option. Click uses this to implement nested subcommands - #: safely. - self.allow_interspersed_args = True - #: This tells the parser how to deal with unknown options. By - #: default it will error out (which is sensible), but there is a - #: second mode where it will ignore it and continue processing - #: after shifting all the unknown options into the resulting args. - self.ignore_unknown_options = False - if ctx is not None: - self.allow_interspersed_args = ctx.allow_interspersed_args - self.ignore_unknown_options = ctx.ignore_unknown_options - self._short_opt = {} - self._long_opt = {} - self._opt_prefixes = {"-", "--"} - self._args = [] - - def add_option(self, opts, dest, action=None, nargs=1, const=None, obj=None): - """Adds a new option named `dest` to the parser. The destination - is not inferred (unlike with optparse) and needs to be explicitly - provided. Action can be any of ``store``, ``store_const``, - ``append``, ``appnd_const`` or ``count``. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - if obj is None: - obj = dest - opts = [normalize_opt(opt, self.ctx) for opt in opts] - option = Option(opts, dest, action=action, nargs=nargs, const=const, obj=obj) - self._opt_prefixes.update(option.prefixes) - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - def add_argument(self, dest, nargs=1, obj=None): - """Adds a positional argument named `dest` to the parser. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - if obj is None: - obj = dest - self._args.append(Argument(dest=dest, nargs=nargs, obj=obj)) - - def parse_args(self, args): - """Parses positional arguments and returns ``(values, args, order)`` - for the parsed options and arguments as well as the leftover - arguments if there are any. The order is a list of objects as they - appear on the command line. If arguments appear multiple times they - will be memorized multiple times as well. - """ - state = ParsingState(args) - try: - self._process_args_for_options(state) - self._process_args_for_args(state) - except UsageError: - if self.ctx is None or not self.ctx.resilient_parsing: - raise - return state.opts, state.largs, state.order - - def _process_args_for_args(self, state): - pargs, args = _unpack_args( - state.largs + state.rargs, [x.nargs for x in self._args] - ) - - for idx, arg in enumerate(self._args): - arg.process(pargs[idx], state) - - state.largs = args - state.rargs = [] - - def _process_args_for_options(self, state): - while state.rargs: - arg = state.rargs.pop(0) - arglen = len(arg) - # Double dashes always handled explicitly regardless of what - # prefixes are valid. - if arg == "--": - return - elif arg[:1] in self._opt_prefixes and arglen > 1: - self._process_opts(arg, state) - elif self.allow_interspersed_args: - state.largs.append(arg) - else: - state.rargs.insert(0, arg) - return - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt(self, opt, explicit_value, state): - if opt not in self._long_opt: - possibilities = [word for word in self._long_opt if word.startswith(opt)] - raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) - - option = self._long_opt[opt] - if option.takes_value: - # At this point it's safe to modify rargs by injecting the - # explicit value, because no exception is raised in this - # branch. This means that the inserted value will be fully - # consumed. - if explicit_value is not None: - state.rargs.insert(0, explicit_value) - - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - elif explicit_value is not None: - raise BadOptionUsage(opt, "{} option does not take a value".format(opt)) - - else: - value = None - - option.process(value, state) - - def _match_short_opt(self, arg, state): - stop = False - i = 1 - prefix = arg[0] - unknown_options = [] - - for ch in arg[1:]: - opt = normalize_opt(prefix + ch, self.ctx) - option = self._short_opt.get(opt) - i += 1 - - if not option: - if self.ignore_unknown_options: - unknown_options.append(ch) - continue - raise NoSuchOption(opt, ctx=self.ctx) - if option.takes_value: - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - state.rargs.insert(0, arg[i:]) - stop = True - - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - else: - value = None - - option.process(value, state) - - if stop: - break - - # If we got any unknown options we re-combinate the string of the - # remaining options and re-attach the prefix, then report that - # to the state as new larg. This way there is basic combinatorics - # that can be achieved while still ignoring unknown arguments. - if self.ignore_unknown_options and unknown_options: - state.largs.append("{}{}".format(prefix, "".join(unknown_options))) - - def _process_opts(self, arg, state): - explicit_value = None - # Long option handling happens in two parts. The first part is - # supporting explicitly attached values. In any case, we will try - # to long match the option first. - if "=" in arg: - long_opt, explicit_value = arg.split("=", 1) - else: - long_opt = arg - norm_long_opt = normalize_opt(long_opt, self.ctx) - - # At this point we will match the (assumed) long option through - # the long option matching code. Note that this allows options - # like "-foo" to be matched as long options. - try: - self._match_long_opt(norm_long_opt, explicit_value, state) - except NoSuchOption: - # At this point the long option matching failed, and we need - # to try with short options. However there is a special rule - # which says, that if we have a two character options prefix - # (applies to "--foo" for instance), we do not dispatch to the - # short option code and will instead raise the no option - # error. - if arg[:2] not in self._opt_prefixes: - return self._match_short_opt(arg, state) - if not self.ignore_unknown_options: - raise - state.largs.append(arg) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/termui.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/termui.py deleted file mode 100644 index 02ef9e9..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/termui.py +++ /dev/null @@ -1,681 +0,0 @@ -import inspect -import io -import itertools -import os -import struct -import sys - -from ._compat import DEFAULT_COLUMNS -from ._compat import get_winterm_size -from ._compat import isatty -from ._compat import raw_input -from ._compat import string_types -from ._compat import strip_ansi -from ._compat import text_type -from ._compat import WIN -from .exceptions import Abort -from .exceptions import UsageError -from .globals import resolve_color_default -from .types import Choice -from .types import convert_type -from .types import Path -from .utils import echo -from .utils import LazyFile - -# The prompt functions to use. The doc tools currently override these -# functions to customize how they work. -visible_prompt_func = raw_input - -_ansi_colors = { - "black": 30, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36, - "white": 37, - "reset": 39, - "bright_black": 90, - "bright_red": 91, - "bright_green": 92, - "bright_yellow": 93, - "bright_blue": 94, - "bright_magenta": 95, - "bright_cyan": 96, - "bright_white": 97, -} -_ansi_reset_all = "\033[0m" - - -def hidden_prompt_func(prompt): - import getpass - - return getpass.getpass(prompt) - - -def _build_prompt( - text, suffix, show_default=False, default=None, show_choices=True, type=None -): - prompt = text - if type is not None and show_choices and isinstance(type, Choice): - prompt += " ({})".format(", ".join(map(str, type.choices))) - if default is not None and show_default: - prompt = "{} [{}]".format(prompt, _format_default(default)) - return prompt + suffix - - -def _format_default(default): - if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): - return default.name - - return default - - -def prompt( - text, - default=None, - hide_input=False, - confirmation_prompt=False, - type=None, - value_proc=None, - prompt_suffix=": ", - show_default=True, - err=False, - show_choices=True, -): - """Prompts a user for input. This is a convenience function that can - be used to prompt a user for input later. - - If the user aborts the input by sending a interrupt signal, this - function will catch it and raise a :exc:`Abort` exception. - - .. versionadded:: 7.0 - Added the show_choices parameter. - - .. versionadded:: 6.0 - Added unicode support for cmd.exe on Windows. - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param text: the text to show for the prompt. - :param default: the default value to use if no input happens. If this - is not given it will prompt until it's aborted. - :param hide_input: if this is set to true then the input value will - be hidden. - :param confirmation_prompt: asks for confirmation for the value. - :param type: the type to use to check the value against. - :param value_proc: if this parameter is provided it's a function that - is invoked instead of the type conversion to - convert a value. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - :param show_choices: Show or hide choices if the passed type is a Choice. - For example if type is a Choice of either day or week, - show_choices is true and text is "Group by" then the - prompt will be "Group by (day, week): ". - """ - result = None - - def prompt_func(text): - f = hidden_prompt_func if hide_input else visible_prompt_func - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(text, nl=False, err=err) - return f("") - except (KeyboardInterrupt, EOFError): - # getpass doesn't print a newline if the user aborts input with ^C. - # Allegedly this behavior is inherited from getpass(3). - # A doc bug has been filed at https://bugs.python.org/issue24711 - if hide_input: - echo(None, err=err) - raise Abort() - - if value_proc is None: - value_proc = convert_type(type, default) - - prompt = _build_prompt( - text, prompt_suffix, show_default, default, show_choices, type - ) - - while 1: - while 1: - value = prompt_func(prompt) - if value: - break - elif default is not None: - if isinstance(value_proc, Path): - # validate Path default value(exists, dir_okay etc.) - value = default - break - return default - try: - result = value_proc(value) - except UsageError as e: - echo("Error: {}".format(e.message), err=err) # noqa: B306 - continue - if not confirmation_prompt: - return result - while 1: - value2 = prompt_func("Repeat for confirmation: ") - if value2: - break - if value == value2: - return result - echo("Error: the two entered values do not match", err=err) - - -def confirm( - text, default=False, abort=False, prompt_suffix=": ", show_default=True, err=False -): - """Prompts for confirmation (yes/no question). - - If the user aborts the input by sending a interrupt signal this - function will catch it and raise a :exc:`Abort` exception. - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param text: the question to ask. - :param default: the default for the prompt. - :param abort: if this is set to `True` a negative answer aborts the - exception by raising :exc:`Abort`. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - prompt = _build_prompt( - text, prompt_suffix, show_default, "Y/n" if default else "y/N" - ) - while 1: - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(prompt, nl=False, err=err) - value = visible_prompt_func("").lower().strip() - except (KeyboardInterrupt, EOFError): - raise Abort() - if value in ("y", "yes"): - rv = True - elif value in ("n", "no"): - rv = False - elif value == "": - rv = default - else: - echo("Error: invalid input", err=err) - continue - break - if abort and not rv: - raise Abort() - return rv - - -def get_terminal_size(): - """Returns the current size of the terminal as tuple in the form - ``(width, height)`` in columns and rows. - """ - # If shutil has get_terminal_size() (Python 3.3 and later) use that - if sys.version_info >= (3, 3): - import shutil - - shutil_get_terminal_size = getattr(shutil, "get_terminal_size", None) - if shutil_get_terminal_size: - sz = shutil_get_terminal_size() - return sz.columns, sz.lines - - # We provide a sensible default for get_winterm_size() when being invoked - # inside a subprocess. Without this, it would not provide a useful input. - if get_winterm_size is not None: - size = get_winterm_size() - if size == (0, 0): - return (79, 24) - else: - return size - - def ioctl_gwinsz(fd): - try: - import fcntl - import termios - - cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234")) - except Exception: - return - return cr - - cr = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - try: - cr = ioctl_gwinsz(fd) - finally: - os.close(fd) - except Exception: - pass - if not cr or not cr[0] or not cr[1]: - cr = (os.environ.get("LINES", 25), os.environ.get("COLUMNS", DEFAULT_COLUMNS)) - return int(cr[1]), int(cr[0]) - - -def echo_via_pager(text_or_generator, color=None): - """This function takes a text and shows it via an environment specific - pager on stdout. - - .. versionchanged:: 3.0 - Added the `color` flag. - - :param text_or_generator: the text to page, or alternatively, a - generator emitting the text to page. - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - color = resolve_color_default(color) - - if inspect.isgeneratorfunction(text_or_generator): - i = text_or_generator() - elif isinstance(text_or_generator, string_types): - i = [text_or_generator] - else: - i = iter(text_or_generator) - - # convert every element of i to a text type if necessary - text_generator = (el if isinstance(el, string_types) else text_type(el) for el in i) - - from ._termui_impl import pager - - return pager(itertools.chain(text_generator, "\n"), color) - - -def progressbar( - iterable=None, - length=None, - label=None, - show_eta=True, - show_percent=None, - show_pos=False, - item_show_func=None, - fill_char="#", - empty_char="-", - bar_template="%(label)s [%(bar)s] %(info)s", - info_sep=" ", - width=36, - file=None, - color=None, -): - """This function creates an iterable context manager that can be used - to iterate over something while showing a progress bar. It will - either iterate over the `iterable` or `length` items (that are counted - up). While iteration happens, this function will print a rendered - progress bar to the given `file` (defaults to stdout) and will attempt - to calculate remaining time and more. By default, this progress bar - will not be rendered if the file is not a terminal. - - The context manager creates the progress bar. When the context - manager is entered the progress bar is already created. With every - iteration over the progress bar, the iterable passed to the bar is - advanced and the bar is updated. When the context manager exits, - a newline is printed and the progress bar is finalized on screen. - - Note: The progress bar is currently designed for use cases where the - total progress can be expected to take at least several seconds. - Because of this, the ProgressBar class object won't display - progress that is considered too fast, and progress where the time - between steps is less than a second. - - No printing must happen or the progress bar will be unintentionally - destroyed. - - Example usage:: - - with progressbar(items) as bar: - for item in bar: - do_something_with(item) - - Alternatively, if no iterable is specified, one can manually update the - progress bar through the `update()` method instead of directly - iterating over the progress bar. The update method accepts the number - of steps to increment the bar with:: - - with progressbar(length=chunks.total_bytes) as bar: - for chunk in chunks: - process_chunk(chunk) - bar.update(chunks.bytes) - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `color` parameter. Added a `update` method to the - progressbar object. - - :param iterable: an iterable to iterate over. If not provided the length - is required. - :param length: the number of items to iterate over. By default the - progressbar will attempt to ask the iterator about its - length, which might or might not work. If an iterable is - also provided this parameter can be used to override the - length. If an iterable is not provided the progress bar - will iterate over a range of that length. - :param label: the label to show next to the progress bar. - :param show_eta: enables or disables the estimated time display. This is - automatically disabled if the length cannot be - determined. - :param show_percent: enables or disables the percentage display. The - default is `True` if the iterable has a length or - `False` if not. - :param show_pos: enables or disables the absolute position display. The - default is `False`. - :param item_show_func: a function called with the current item which - can return a string to show the current item - next to the progress bar. Note that the current - item can be `None`! - :param fill_char: the character to use to show the filled part of the - progress bar. - :param empty_char: the character to use to show the non-filled part of - the progress bar. - :param bar_template: the format string to use as template for the bar. - The parameters in it are ``label`` for the label, - ``bar`` for the progress bar and ``info`` for the - info section. - :param info_sep: the separator between multiple info items (eta etc.) - :param width: the width of the progress bar in characters, 0 means full - terminal width - :param file: the file to write to. If this is not a terminal then - only the label is printed. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are included anywhere in the progress bar output - which is not the case by default. - """ - from ._termui_impl import ProgressBar - - color = resolve_color_default(color) - return ProgressBar( - iterable=iterable, - length=length, - show_eta=show_eta, - show_percent=show_percent, - show_pos=show_pos, - item_show_func=item_show_func, - fill_char=fill_char, - empty_char=empty_char, - bar_template=bar_template, - info_sep=info_sep, - file=file, - label=label, - width=width, - color=color, - ) - - -def clear(): - """Clears the terminal screen. This will have the effect of clearing - the whole visible space of the terminal and moving the cursor to the - top left. This does not do anything if not connected to a terminal. - - .. versionadded:: 2.0 - """ - if not isatty(sys.stdout): - return - # If we're on Windows and we don't have colorama available, then we - # clear the screen by shelling out. Otherwise we can use an escape - # sequence. - if WIN: - os.system("cls") - else: - sys.stdout.write("\033[2J\033[1;1H") - - -def style( - text, - fg=None, - bg=None, - bold=None, - dim=None, - underline=None, - blink=None, - reverse=None, - reset=True, -): - """Styles a text with ANSI styles and returns the new string. By - default the styling is self contained which means that at the end - of the string a reset code is issued. This can be prevented by - passing ``reset=False``. - - Examples:: - - click.echo(click.style('Hello World!', fg='green')) - click.echo(click.style('ATTENTION!', blink=True)) - click.echo(click.style('Some things', reverse=True, fg='cyan')) - - Supported color names: - - * ``black`` (might be a gray) - * ``red`` - * ``green`` - * ``yellow`` (might be an orange) - * ``blue`` - * ``magenta`` - * ``cyan`` - * ``white`` (might be light gray) - * ``bright_black`` - * ``bright_red`` - * ``bright_green`` - * ``bright_yellow`` - * ``bright_blue`` - * ``bright_magenta`` - * ``bright_cyan`` - * ``bright_white`` - * ``reset`` (reset the color code only) - - .. versionadded:: 2.0 - - .. versionadded:: 7.0 - Added support for bright colors. - - :param text: the string to style with ansi codes. - :param fg: if provided this will become the foreground color. - :param bg: if provided this will become the background color. - :param bold: if provided this will enable or disable bold mode. - :param dim: if provided this will enable or disable dim mode. This is - badly supported. - :param underline: if provided this will enable or disable underline. - :param blink: if provided this will enable or disable blinking. - :param reverse: if provided this will enable or disable inverse - rendering (foreground becomes background and the - other way round). - :param reset: by default a reset-all code is added at the end of the - string which means that styles do not carry over. This - can be disabled to compose styles. - """ - bits = [] - if fg: - try: - bits.append("\033[{}m".format(_ansi_colors[fg])) - except KeyError: - raise TypeError("Unknown color '{}'".format(fg)) - if bg: - try: - bits.append("\033[{}m".format(_ansi_colors[bg] + 10)) - except KeyError: - raise TypeError("Unknown color '{}'".format(bg)) - if bold is not None: - bits.append("\033[{}m".format(1 if bold else 22)) - if dim is not None: - bits.append("\033[{}m".format(2 if dim else 22)) - if underline is not None: - bits.append("\033[{}m".format(4 if underline else 24)) - if blink is not None: - bits.append("\033[{}m".format(5 if blink else 25)) - if reverse is not None: - bits.append("\033[{}m".format(7 if reverse else 27)) - bits.append(text) - if reset: - bits.append(_ansi_reset_all) - return "".join(bits) - - -def unstyle(text): - """Removes ANSI styling information from a string. Usually it's not - necessary to use this function as Click's echo function will - automatically remove styling if necessary. - - .. versionadded:: 2.0 - - :param text: the text to remove style information from. - """ - return strip_ansi(text) - - -def secho(message=None, file=None, nl=True, err=False, color=None, **styles): - """This function combines :func:`echo` and :func:`style` into one - call. As such the following two calls are the same:: - - click.secho('Hello World!', fg='green') - click.echo(click.style('Hello World!', fg='green')) - - All keyword arguments are forwarded to the underlying functions - depending on which one they go with. - - .. versionadded:: 2.0 - """ - if message is not None: - message = style(message, **styles) - return echo(message, file=file, nl=nl, err=err, color=color) - - -def edit( - text=None, editor=None, env=None, require_save=True, extension=".txt", filename=None -): - r"""Edits the given text in the defined editor. If an editor is given - (should be the full path to the executable but the regular operating - system search path is used for finding the executable) it overrides - the detected editor. Optionally, some environment variables can be - used. If the editor is closed without changes, `None` is returned. In - case a file is edited directly the return value is always `None` and - `require_save` and `extension` are ignored. - - If the editor cannot be opened a :exc:`UsageError` is raised. - - Note for Windows: to simplify cross-platform usage, the newlines are - automatically converted from POSIX to Windows and vice versa. As such, - the message here will have ``\n`` as newline markers. - - :param text: the text to edit. - :param editor: optionally the editor to use. Defaults to automatic - detection. - :param env: environment variables to forward to the editor. - :param require_save: if this is true, then not saving in the editor - will make the return value become `None`. - :param extension: the extension to tell the editor about. This defaults - to `.txt` but changing this might change syntax - highlighting. - :param filename: if provided it will edit this file instead of the - provided text contents. It will not use a temporary - file as an indirection in that case. - """ - from ._termui_impl import Editor - - editor = Editor( - editor=editor, env=env, require_save=require_save, extension=extension - ) - if filename is None: - return editor.edit(text) - editor.edit_file(filename) - - -def launch(url, wait=False, locate=False): - """This function launches the given URL (or filename) in the default - viewer application for this file type. If this is an executable, it - might launch the executable in a new session. The return value is - the exit code of the launched application. Usually, ``0`` indicates - success. - - Examples:: - - click.launch('https://click.palletsprojects.com/') - click.launch('/my/downloaded/file', locate=True) - - .. versionadded:: 2.0 - - :param url: URL or filename of the thing to launch. - :param wait: waits for the program to stop. - :param locate: if this is set to `True` then instead of launching the - application associated with the URL it will attempt to - launch a file manager with the file located. This - might have weird effects if the URL does not point to - the filesystem. - """ - from ._termui_impl import open_url - - return open_url(url, wait=wait, locate=locate) - - -# If this is provided, getchar() calls into this instead. This is used -# for unittesting purposes. -_getchar = None - - -def getchar(echo=False): - """Fetches a single character from the terminal and returns it. This - will always return a unicode character and under certain rare - circumstances this might return more than one character. The - situations which more than one character is returned is when for - whatever reason multiple characters end up in the terminal buffer or - standard input was not actually a terminal. - - Note that this will always read from the terminal, even if something - is piped into the standard input. - - Note for Windows: in rare cases when typing non-ASCII characters, this - function might wait for a second character and then return both at once. - This is because certain Unicode characters look like special-key markers. - - .. versionadded:: 2.0 - - :param echo: if set to `True`, the character read will also show up on - the terminal. The default is to not show it. - """ - f = _getchar - if f is None: - from ._termui_impl import getchar as f - return f(echo) - - -def raw_terminal(): - from ._termui_impl import raw_terminal as f - - return f() - - -def pause(info="Press any key to continue ...", err=False): - """This command stops execution and waits for the user to press any - key to continue. This is similar to the Windows batch "pause" - command. If the program is not run through a terminal, this command - will instead do nothing. - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param info: the info string to print before pausing. - :param err: if set to message goes to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - if not isatty(sys.stdin) or not isatty(sys.stdout): - return - try: - if info: - echo(info, nl=False, err=err) - try: - getchar() - except (KeyboardInterrupt, EOFError): - pass - finally: - if info: - echo(err=err) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/testing.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/testing.py deleted file mode 100644 index a3dba3b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/testing.py +++ /dev/null @@ -1,382 +0,0 @@ -import contextlib -import os -import shlex -import shutil -import sys -import tempfile - -from . import formatting -from . import termui -from . import utils -from ._compat import iteritems -from ._compat import PY2 -from ._compat import string_types - - -if PY2: - from cStringIO import StringIO -else: - import io - from ._compat import _find_binary_reader - - -class EchoingStdin(object): - def __init__(self, input, output): - self._input = input - self._output = output - - def __getattr__(self, x): - return getattr(self._input, x) - - def _echo(self, rv): - self._output.write(rv) - return rv - - def read(self, n=-1): - return self._echo(self._input.read(n)) - - def readline(self, n=-1): - return self._echo(self._input.readline(n)) - - def readlines(self): - return [self._echo(x) for x in self._input.readlines()] - - def __iter__(self): - return iter(self._echo(x) for x in self._input) - - def __repr__(self): - return repr(self._input) - - -def make_input_stream(input, charset): - # Is already an input stream. - if hasattr(input, "read"): - if PY2: - return input - rv = _find_binary_reader(input) - if rv is not None: - return rv - raise TypeError("Could not find binary reader for input stream.") - - if input is None: - input = b"" - elif not isinstance(input, bytes): - input = input.encode(charset) - if PY2: - return StringIO(input) - return io.BytesIO(input) - - -class Result(object): - """Holds the captured result of an invoked CLI script.""" - - def __init__( - self, runner, stdout_bytes, stderr_bytes, exit_code, exception, exc_info=None - ): - #: The runner that created the result - self.runner = runner - #: The standard output as bytes. - self.stdout_bytes = stdout_bytes - #: The standard error as bytes, or None if not available - self.stderr_bytes = stderr_bytes - #: The exit code as integer. - self.exit_code = exit_code - #: The exception that happened if one did. - self.exception = exception - #: The traceback - self.exc_info = exc_info - - @property - def output(self): - """The (standard) output as unicode string.""" - return self.stdout - - @property - def stdout(self): - """The standard output as unicode string.""" - return self.stdout_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - @property - def stderr(self): - """The standard error as unicode string.""" - if self.stderr_bytes is None: - raise ValueError("stderr not separately captured") - return self.stderr_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - def __repr__(self): - return "<{} {}>".format( - type(self).__name__, repr(self.exception) if self.exception else "okay" - ) - - -class CliRunner(object): - """The CLI runner provides functionality to invoke a Click command line - script for unittesting purposes in a isolated environment. This only - works in single-threaded systems without any concurrency as it changes the - global interpreter state. - - :param charset: the character set for the input and output data. This is - UTF-8 by default and should not be changed currently as - the reporting to Click only works in Python 2 properly. - :param env: a dictionary with environment variables for overriding. - :param echo_stdin: if this is set to `True`, then reading from stdin writes - to stdout. This is useful for showing examples in - some circumstances. Note that regular prompts - will automatically echo the input. - :param mix_stderr: if this is set to `False`, then stdout and stderr are - preserved as independent streams. This is useful for - Unix-philosophy apps that have predictable stdout and - noisy stderr, such that each may be measured - independently - """ - - def __init__(self, charset=None, env=None, echo_stdin=False, mix_stderr=True): - if charset is None: - charset = "utf-8" - self.charset = charset - self.env = env or {} - self.echo_stdin = echo_stdin - self.mix_stderr = mix_stderr - - def get_default_prog_name(self, cli): - """Given a command object it will return the default program name - for it. The default is the `name` attribute or ``"root"`` if not - set. - """ - return cli.name or "root" - - def make_env(self, overrides=None): - """Returns the environment overrides for invoking a script.""" - rv = dict(self.env) - if overrides: - rv.update(overrides) - return rv - - @contextlib.contextmanager - def isolation(self, input=None, env=None, color=False): - """A context manager that sets up the isolation for invoking of a - command line tool. This sets up stdin with the given input data - and `os.environ` with the overrides from the given dictionary. - This also rebinds some internals in Click to be mocked (like the - prompt functionality). - - This is automatically done in the :meth:`invoke` method. - - .. versionadded:: 4.0 - The ``color`` parameter was added. - - :param input: the input stream to put into sys.stdin. - :param env: the environment overrides as dictionary. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - """ - input = make_input_stream(input, self.charset) - - old_stdin = sys.stdin - old_stdout = sys.stdout - old_stderr = sys.stderr - old_forced_width = formatting.FORCED_WIDTH - formatting.FORCED_WIDTH = 80 - - env = self.make_env(env) - - if PY2: - bytes_output = StringIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - sys.stdout = bytes_output - if not self.mix_stderr: - bytes_error = StringIO() - sys.stderr = bytes_error - else: - bytes_output = io.BytesIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - input = io.TextIOWrapper(input, encoding=self.charset) - sys.stdout = io.TextIOWrapper(bytes_output, encoding=self.charset) - if not self.mix_stderr: - bytes_error = io.BytesIO() - sys.stderr = io.TextIOWrapper(bytes_error, encoding=self.charset) - - if self.mix_stderr: - sys.stderr = sys.stdout - - sys.stdin = input - - def visible_input(prompt=None): - sys.stdout.write(prompt or "") - val = input.readline().rstrip("\r\n") - sys.stdout.write("{}\n".format(val)) - sys.stdout.flush() - return val - - def hidden_input(prompt=None): - sys.stdout.write("{}\n".format(prompt or "")) - sys.stdout.flush() - return input.readline().rstrip("\r\n") - - def _getchar(echo): - char = sys.stdin.read(1) - if echo: - sys.stdout.write(char) - sys.stdout.flush() - return char - - default_color = color - - def should_strip_ansi(stream=None, color=None): - if color is None: - return not default_color - return not color - - old_visible_prompt_func = termui.visible_prompt_func - old_hidden_prompt_func = termui.hidden_prompt_func - old__getchar_func = termui._getchar - old_should_strip_ansi = utils.should_strip_ansi - termui.visible_prompt_func = visible_input - termui.hidden_prompt_func = hidden_input - termui._getchar = _getchar - utils.should_strip_ansi = should_strip_ansi - - old_env = {} - try: - for key, value in iteritems(env): - old_env[key] = os.environ.get(key) - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - yield (bytes_output, not self.mix_stderr and bytes_error) - finally: - for key, value in iteritems(old_env): - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - sys.stdout = old_stdout - sys.stderr = old_stderr - sys.stdin = old_stdin - termui.visible_prompt_func = old_visible_prompt_func - termui.hidden_prompt_func = old_hidden_prompt_func - termui._getchar = old__getchar_func - utils.should_strip_ansi = old_should_strip_ansi - formatting.FORCED_WIDTH = old_forced_width - - def invoke( - self, - cli, - args=None, - input=None, - env=None, - catch_exceptions=True, - color=False, - **extra - ): - """Invokes a command in an isolated environment. The arguments are - forwarded directly to the command line script, the `extra` keyword - arguments are passed to the :meth:`~clickpkg.Command.main` function of - the command. - - This returns a :class:`Result` object. - - .. versionadded:: 3.0 - The ``catch_exceptions`` parameter was added. - - .. versionchanged:: 3.0 - The result object now has an `exc_info` attribute with the - traceback if available. - - .. versionadded:: 4.0 - The ``color`` parameter was added. - - :param cli: the command to invoke - :param args: the arguments to invoke. It may be given as an iterable - or a string. When given as string it will be interpreted - as a Unix shell command. More details at - :func:`shlex.split`. - :param input: the input data for `sys.stdin`. - :param env: the environment overrides. - :param catch_exceptions: Whether to catch any other exceptions than - ``SystemExit``. - :param extra: the keyword arguments to pass to :meth:`main`. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - """ - exc_info = None - with self.isolation(input=input, env=env, color=color) as outstreams: - exception = None - exit_code = 0 - - if isinstance(args, string_types): - args = shlex.split(args) - - try: - prog_name = extra.pop("prog_name") - except KeyError: - prog_name = self.get_default_prog_name(cli) - - try: - cli.main(args=args or (), prog_name=prog_name, **extra) - except SystemExit as e: - exc_info = sys.exc_info() - exit_code = e.code - if exit_code is None: - exit_code = 0 - - if exit_code != 0: - exception = e - - if not isinstance(exit_code, int): - sys.stdout.write(str(exit_code)) - sys.stdout.write("\n") - exit_code = 1 - - except Exception as e: - if not catch_exceptions: - raise - exception = e - exit_code = 1 - exc_info = sys.exc_info() - finally: - sys.stdout.flush() - stdout = outstreams[0].getvalue() - if self.mix_stderr: - stderr = None - else: - stderr = outstreams[1].getvalue() - - return Result( - runner=self, - stdout_bytes=stdout, - stderr_bytes=stderr, - exit_code=exit_code, - exception=exception, - exc_info=exc_info, - ) - - @contextlib.contextmanager - def isolated_filesystem(self): - """A context manager that creates a temporary folder and changes - the current working directory to it for isolated filesystem tests. - """ - cwd = os.getcwd() - t = tempfile.mkdtemp() - os.chdir(t) - try: - yield t - finally: - os.chdir(cwd) - try: - shutil.rmtree(t) - except (OSError, IOError): # noqa: B014 - pass diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/types.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/types.py deleted file mode 100644 index 505c39f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/types.py +++ /dev/null @@ -1,762 +0,0 @@ -import os -import stat -from datetime import datetime - -from ._compat import _get_argv_encoding -from ._compat import filename_to_ui -from ._compat import get_filesystem_encoding -from ._compat import get_streerror -from ._compat import open_stream -from ._compat import PY2 -from ._compat import text_type -from .exceptions import BadParameter -from .utils import LazyFile -from .utils import safecall - - -class ParamType(object): - """Helper for converting values through types. The following is - necessary for a valid type: - - * it needs a name - * it needs to pass through None unchanged - * it needs to convert from a string - * it needs to convert its result type through unchanged - (eg: needs to be idempotent) - * it needs to be able to deal with param and context being `None`. - This can be the case when the object is used with prompt - inputs. - """ - - is_composite = False - - #: the descriptive name of this type - name = None - - #: if a list of this type is expected and the value is pulled from a - #: string environment variable, this is what splits it up. `None` - #: means any whitespace. For all parameters the general rule is that - #: whitespace splits them up. The exception are paths and files which - #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on - #: Windows). - envvar_list_splitter = None - - def __call__(self, value, param=None, ctx=None): - if value is not None: - return self.convert(value, param, ctx) - - def get_metavar(self, param): - """Returns the metavar default for this param if it provides one.""" - - def get_missing_message(self, param): - """Optionally might return extra information about a missing - parameter. - - .. versionadded:: 2.0 - """ - - def convert(self, value, param, ctx): - """Converts the value. This is not invoked for values that are - `None` (the missing value). - """ - return value - - def split_envvar_value(self, rv): - """Given a value from an environment variable this splits it up - into small chunks depending on the defined envvar list splitter. - - If the splitter is set to `None`, which means that whitespace splits, - then leading and trailing whitespace is ignored. Otherwise, leading - and trailing splitters usually lead to empty items being included. - """ - return (rv or "").split(self.envvar_list_splitter) - - def fail(self, message, param=None, ctx=None): - """Helper method to fail with an invalid value message.""" - raise BadParameter(message, ctx=ctx, param=param) - - -class CompositeParamType(ParamType): - is_composite = True - - @property - def arity(self): - raise NotImplementedError() - - -class FuncParamType(ParamType): - def __init__(self, func): - self.name = func.__name__ - self.func = func - - def convert(self, value, param, ctx): - try: - return self.func(value) - except ValueError: - try: - value = text_type(value) - except UnicodeError: - value = str(value).decode("utf-8", "replace") - self.fail(value, param, ctx) - - -class UnprocessedParamType(ParamType): - name = "text" - - def convert(self, value, param, ctx): - return value - - def __repr__(self): - return "UNPROCESSED" - - -class StringParamType(ParamType): - name = "text" - - def convert(self, value, param, ctx): - if isinstance(value, bytes): - enc = _get_argv_encoding() - try: - value = value.decode(enc) - except UnicodeError: - fs_enc = get_filesystem_encoding() - if fs_enc != enc: - try: - value = value.decode(fs_enc) - except UnicodeError: - value = value.decode("utf-8", "replace") - else: - value = value.decode("utf-8", "replace") - return value - return value - - def __repr__(self): - return "STRING" - - -class Choice(ParamType): - """The choice type allows a value to be checked against a fixed set - of supported values. All of these values have to be strings. - - You should only pass a list or tuple of choices. Other iterables - (like generators) may lead to surprising results. - - The resulting value will always be one of the originally passed choices - regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` - being specified. - - See :ref:`choice-opts` for an example. - - :param case_sensitive: Set to false to make choices case - insensitive. Defaults to true. - """ - - name = "choice" - - def __init__(self, choices, case_sensitive=True): - self.choices = choices - self.case_sensitive = case_sensitive - - def get_metavar(self, param): - return "[{}]".format("|".join(self.choices)) - - def get_missing_message(self, param): - return "Choose from:\n\t{}.".format(",\n\t".join(self.choices)) - - def convert(self, value, param, ctx): - # Match through normalization and case sensitivity - # first do token_normalize_func, then lowercase - # preserve original `value` to produce an accurate message in - # `self.fail` - normed_value = value - normed_choices = {choice: choice for choice in self.choices} - - if ctx is not None and ctx.token_normalize_func is not None: - normed_value = ctx.token_normalize_func(value) - normed_choices = { - ctx.token_normalize_func(normed_choice): original - for normed_choice, original in normed_choices.items() - } - - if not self.case_sensitive: - if PY2: - lower = str.lower - else: - lower = str.casefold - - normed_value = lower(normed_value) - normed_choices = { - lower(normed_choice): original - for normed_choice, original in normed_choices.items() - } - - if normed_value in normed_choices: - return normed_choices[normed_value] - - self.fail( - "invalid choice: {}. (choose from {})".format( - value, ", ".join(self.choices) - ), - param, - ctx, - ) - - def __repr__(self): - return "Choice('{}')".format(list(self.choices)) - - -class DateTime(ParamType): - """The DateTime type converts date strings into `datetime` objects. - - The format strings which are checked are configurable, but default to some - common (non-timezone aware) ISO 8601 formats. - - When specifying *DateTime* formats, you should only pass a list or a tuple. - Other iterables, like generators, may lead to surprising results. - - The format strings are processed using ``datetime.strptime``, and this - consequently defines the format strings which are allowed. - - Parsing is tried using each format, in order, and the first format which - parses successfully is used. - - :param formats: A list or tuple of date format strings, in the order in - which they should be tried. Defaults to - ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, - ``'%Y-%m-%d %H:%M:%S'``. - """ - - name = "datetime" - - def __init__(self, formats=None): - self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] - - def get_metavar(self, param): - return "[{}]".format("|".join(self.formats)) - - def _try_to_convert_date(self, value, format): - try: - return datetime.strptime(value, format) - except ValueError: - return None - - def convert(self, value, param, ctx): - # Exact match - for format in self.formats: - dtime = self._try_to_convert_date(value, format) - if dtime: - return dtime - - self.fail( - "invalid datetime format: {}. (choose from {})".format( - value, ", ".join(self.formats) - ) - ) - - def __repr__(self): - return "DateTime" - - -class IntParamType(ParamType): - name = "integer" - - def convert(self, value, param, ctx): - try: - return int(value) - except ValueError: - self.fail("{} is not a valid integer".format(value), param, ctx) - - def __repr__(self): - return "INT" - - -class IntRange(IntParamType): - """A parameter that works similar to :data:`click.INT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. - - See :ref:`ranges` for an example. - """ - - name = "integer range" - - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp - - def convert(self, value, param, ctx): - rv = IntParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if ( - self.min is not None - and rv < self.min - or self.max is not None - and rv > self.max - ): - if self.min is None: - self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), - param, - ctx, - ) - elif self.max is None: - self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), - param, - ctx, - ) - else: - self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), - param, - ctx, - ) - return rv - - def __repr__(self): - return "IntRange({}, {})".format(self.min, self.max) - - -class FloatParamType(ParamType): - name = "float" - - def convert(self, value, param, ctx): - try: - return float(value) - except ValueError: - self.fail( - "{} is not a valid floating point value".format(value), param, ctx - ) - - def __repr__(self): - return "FLOAT" - - -class FloatRange(FloatParamType): - """A parameter that works similar to :data:`click.FLOAT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. - - See :ref:`ranges` for an example. - """ - - name = "float range" - - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp - - def convert(self, value, param, ctx): - rv = FloatParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if ( - self.min is not None - and rv < self.min - or self.max is not None - and rv > self.max - ): - if self.min is None: - self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), - param, - ctx, - ) - elif self.max is None: - self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), - param, - ctx, - ) - else: - self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), - param, - ctx, - ) - return rv - - def __repr__(self): - return "FloatRange({}, {})".format(self.min, self.max) - - -class BoolParamType(ParamType): - name = "boolean" - - def convert(self, value, param, ctx): - if isinstance(value, bool): - return bool(value) - value = value.lower() - if value in ("true", "t", "1", "yes", "y"): - return True - elif value in ("false", "f", "0", "no", "n"): - return False - self.fail("{} is not a valid boolean".format(value), param, ctx) - - def __repr__(self): - return "BOOL" - - -class UUIDParameterType(ParamType): - name = "uuid" - - def convert(self, value, param, ctx): - import uuid - - try: - if PY2 and isinstance(value, text_type): - value = value.encode("ascii") - return uuid.UUID(value) - except ValueError: - self.fail("{} is not a valid UUID value".format(value), param, ctx) - - def __repr__(self): - return "UUID" - - -class File(ParamType): - """Declares a parameter to be a file for reading or writing. The file - is automatically closed once the context tears down (after the command - finished working). - - Files can be opened for reading or writing. The special value ``-`` - indicates stdin or stdout depending on the mode. - - By default, the file is opened for reading text data, but it can also be - opened in binary mode or for writing. The encoding parameter can be used - to force a specific encoding. - - The `lazy` flag controls if the file should be opened immediately or upon - first IO. The default is to be non-lazy for standard input and output - streams as well as files opened for reading, `lazy` otherwise. When opening a - file lazily for reading, it is still opened temporarily for validation, but - will not be held open until first IO. lazy is mainly useful when opening - for writing to avoid creating the file until it is needed. - - Starting with Click 2.0, files can also be opened atomically in which - case all writes go into a separate file in the same folder and upon - completion the file will be moved over to the original location. This - is useful if a file regularly read by other users is modified. - - See :ref:`file-args` for more information. - """ - - name = "filename" - envvar_list_splitter = os.path.pathsep - - def __init__( - self, mode="r", encoding=None, errors="strict", lazy=None, atomic=False - ): - self.mode = mode - self.encoding = encoding - self.errors = errors - self.lazy = lazy - self.atomic = atomic - - def resolve_lazy_flag(self, value): - if self.lazy is not None: - return self.lazy - if value == "-": - return False - elif "w" in self.mode: - return True - return False - - def convert(self, value, param, ctx): - try: - if hasattr(value, "read") or hasattr(value, "write"): - return value - - lazy = self.resolve_lazy_flag(value) - - if lazy: - f = LazyFile( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - if ctx is not None: - ctx.call_on_close(f.close_intelligently) - return f - - f, should_close = open_stream( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - # If a context is provided, we automatically close the file - # at the end of the context execution (or flush out). If a - # context does not exist, it's the caller's responsibility to - # properly close the file. This for instance happens when the - # type is used with prompts. - if ctx is not None: - if should_close: - ctx.call_on_close(safecall(f.close)) - else: - ctx.call_on_close(safecall(f.flush)) - return f - except (IOError, OSError) as e: # noqa: B014 - self.fail( - "Could not open file: {}: {}".format( - filename_to_ui(value), get_streerror(e) - ), - param, - ctx, - ) - - -class Path(ParamType): - """The path type is similar to the :class:`File` type but it performs - different checks. First of all, instead of returning an open file - handle it returns just the filename. Secondly, it can perform various - basic checks about what the file or directory should be. - - .. versionchanged:: 6.0 - `allow_dash` was added. - - :param exists: if set to true, the file or directory needs to exist for - this value to be valid. If this is not required and a - file does indeed not exist, then all further checks are - silently skipped. - :param file_okay: controls if a file is a possible value. - :param dir_okay: controls if a directory is a possible value. - :param writable: if true, a writable check is performed. - :param readable: if true, a readable check is performed. - :param resolve_path: if this is true, then the path is fully resolved - before the value is passed onwards. This means - that it's absolute and symlinks are resolved. It - will not expand a tilde-prefix, as this is - supposed to be done by the shell only. - :param allow_dash: If this is set to `True`, a single dash to indicate - standard streams is permitted. - :param path_type: optionally a string type that should be used to - represent the path. The default is `None` which - means the return value will be either bytes or - unicode depending on what makes most sense given the - input data Click deals with. - """ - - envvar_list_splitter = os.path.pathsep - - def __init__( - self, - exists=False, - file_okay=True, - dir_okay=True, - writable=False, - readable=True, - resolve_path=False, - allow_dash=False, - path_type=None, - ): - self.exists = exists - self.file_okay = file_okay - self.dir_okay = dir_okay - self.writable = writable - self.readable = readable - self.resolve_path = resolve_path - self.allow_dash = allow_dash - self.type = path_type - - if self.file_okay and not self.dir_okay: - self.name = "file" - self.path_type = "File" - elif self.dir_okay and not self.file_okay: - self.name = "directory" - self.path_type = "Directory" - else: - self.name = "path" - self.path_type = "Path" - - def coerce_path_result(self, rv): - if self.type is not None and not isinstance(rv, self.type): - if self.type is text_type: - rv = rv.decode(get_filesystem_encoding()) - else: - rv = rv.encode(get_filesystem_encoding()) - return rv - - def convert(self, value, param, ctx): - rv = value - - is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") - - if not is_dash: - if self.resolve_path: - rv = os.path.realpath(rv) - - try: - st = os.stat(rv) - except OSError: - if not self.exists: - return self.coerce_path_result(rv) - self.fail( - "{} '{}' does not exist.".format( - self.path_type, filename_to_ui(value) - ), - param, - ctx, - ) - - if not self.file_okay and stat.S_ISREG(st.st_mode): - self.fail( - "{} '{}' is a file.".format(self.path_type, filename_to_ui(value)), - param, - ctx, - ) - if not self.dir_okay and stat.S_ISDIR(st.st_mode): - self.fail( - "{} '{}' is a directory.".format( - self.path_type, filename_to_ui(value) - ), - param, - ctx, - ) - if self.writable and not os.access(value, os.W_OK): - self.fail( - "{} '{}' is not writable.".format( - self.path_type, filename_to_ui(value) - ), - param, - ctx, - ) - if self.readable and not os.access(value, os.R_OK): - self.fail( - "{} '{}' is not readable.".format( - self.path_type, filename_to_ui(value) - ), - param, - ctx, - ) - - return self.coerce_path_result(rv) - - -class Tuple(CompositeParamType): - """The default behavior of Click is to apply a type on a value directly. - This works well in most cases, except for when `nargs` is set to a fixed - count and different types should be used for different items. In this - case the :class:`Tuple` type can be used. This type can only be used - if `nargs` is set to a fixed number. - - For more information see :ref:`tuple-type`. - - This can be selected by using a Python tuple literal as a type. - - :param types: a list of types that should be used for the tuple items. - """ - - def __init__(self, types): - self.types = [convert_type(ty) for ty in types] - - @property - def name(self): - return "<{}>".format(" ".join(ty.name for ty in self.types)) - - @property - def arity(self): - return len(self.types) - - def convert(self, value, param, ctx): - if len(value) != len(self.types): - raise TypeError( - "It would appear that nargs is set to conflict with the" - " composite type arity." - ) - return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) - - -def convert_type(ty, default=None): - """Converts a callable or python type into the most appropriate - param type. - """ - guessed_type = False - if ty is None and default is not None: - if isinstance(default, tuple): - ty = tuple(map(type, default)) - else: - ty = type(default) - guessed_type = True - - if isinstance(ty, tuple): - return Tuple(ty) - if isinstance(ty, ParamType): - return ty - if ty is text_type or ty is str or ty is None: - return STRING - if ty is int: - return INT - # Booleans are only okay if not guessed. This is done because for - # flags the default value is actually a bit of a lie in that it - # indicates which of the flags is the one we want. See get_default() - # for more information. - if ty is bool and not guessed_type: - return BOOL - if ty is float: - return FLOAT - if guessed_type: - return STRING - - # Catch a common mistake - if __debug__: - try: - if issubclass(ty, ParamType): - raise AssertionError( - "Attempted to use an uninstantiated parameter type ({}).".format(ty) - ) - except TypeError: - pass - return FuncParamType(ty) - - -#: A dummy parameter type that just does nothing. From a user's -#: perspective this appears to just be the same as `STRING` but internally -#: no string conversion takes place. This is necessary to achieve the -#: same bytes/unicode behavior on Python 2/3 in situations where you want -#: to not convert argument types. This is usually useful when working -#: with file paths as they can appear in bytes and unicode. -#: -#: For path related uses the :class:`Path` type is a better choice but -#: there are situations where an unprocessed type is useful which is why -#: it is is provided. -#: -#: .. versionadded:: 4.0 -UNPROCESSED = UnprocessedParamType() - -#: A unicode string parameter type which is the implicit default. This -#: can also be selected by using ``str`` as type. -STRING = StringParamType() - -#: An integer parameter. This can also be selected by using ``int`` as -#: type. -INT = IntParamType() - -#: A floating point value parameter. This can also be selected by using -#: ``float`` as type. -FLOAT = FloatParamType() - -#: A boolean parameter. This is the default for boolean flags. This can -#: also be selected by using ``bool`` as a type. -BOOL = BoolParamType() - -#: A UUID parameter. -UUID = UUIDParameterType() diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/utils.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/utils.py deleted file mode 100644 index 79265e7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/click/utils.py +++ /dev/null @@ -1,455 +0,0 @@ -import os -import sys - -from ._compat import _default_text_stderr -from ._compat import _default_text_stdout -from ._compat import auto_wrap_for_ansi -from ._compat import binary_streams -from ._compat import filename_to_ui -from ._compat import get_filesystem_encoding -from ._compat import get_streerror -from ._compat import is_bytes -from ._compat import open_stream -from ._compat import PY2 -from ._compat import should_strip_ansi -from ._compat import string_types -from ._compat import strip_ansi -from ._compat import text_streams -from ._compat import text_type -from ._compat import WIN -from .globals import resolve_color_default - -if not PY2: - from ._compat import _find_binary_writer -elif WIN: - from ._winconsole import _get_windows_argv - from ._winconsole import _hash_py_argv - from ._winconsole import _initial_argv_hash - -echo_native_types = string_types + (bytes, bytearray) - - -def _posixify(name): - return "-".join(name.split()).lower() - - -def safecall(func): - """Wraps a function so that it swallows exceptions.""" - - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except Exception: - pass - - return wrapper - - -def make_str(value): - """Converts a value into a valid string.""" - if isinstance(value, bytes): - try: - return value.decode(get_filesystem_encoding()) - except UnicodeError: - return value.decode("utf-8", "replace") - return text_type(value) - - -def make_default_short_help(help, max_length=45): - """Return a condensed version of help string.""" - words = help.split() - total_length = 0 - result = [] - done = False - - for word in words: - if word[-1:] == ".": - done = True - new_length = 1 + len(word) if result else len(word) - if total_length + new_length > max_length: - result.append("...") - done = True - else: - if result: - result.append(" ") - result.append(word) - if done: - break - total_length += new_length - - return "".join(result) - - -class LazyFile(object): - """A lazy file works like a regular file but it does not fully open - the file but it does perform some basic checks early to see if the - filename parameter does make sense. This is useful for safely opening - files for writing. - """ - - def __init__( - self, filename, mode="r", encoding=None, errors="strict", atomic=False - ): - self.name = filename - self.mode = mode - self.encoding = encoding - self.errors = errors - self.atomic = atomic - - if filename == "-": - self._f, self.should_close = open_stream(filename, mode, encoding, errors) - else: - if "r" in mode: - # Open and close the file in case we're opening it for - # reading so that we can catch at least some errors in - # some cases early. - open(filename, mode).close() - self._f = None - self.should_close = True - - def __getattr__(self, name): - return getattr(self.open(), name) - - def __repr__(self): - if self._f is not None: - return repr(self._f) - return "".format(self.name, self.mode) - - def open(self): - """Opens the file if it's not yet open. This call might fail with - a :exc:`FileError`. Not handling this error will produce an error - that Click shows. - """ - if self._f is not None: - return self._f - try: - rv, self.should_close = open_stream( - self.name, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - except (IOError, OSError) as e: # noqa: E402 - from .exceptions import FileError - - raise FileError(self.name, hint=get_streerror(e)) - self._f = rv - return rv - - def close(self): - """Closes the underlying file, no matter what.""" - if self._f is not None: - self._f.close() - - def close_intelligently(self): - """This function only closes the file if it was opened by the lazy - file wrapper. For instance this will never close stdin. - """ - if self.should_close: - self.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close_intelligently() - - def __iter__(self): - self.open() - return iter(self._f) - - -class KeepOpenFile(object): - def __init__(self, file): - self._file = file - - def __getattr__(self, name): - return getattr(self._file, name) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - pass - - def __repr__(self): - return repr(self._file) - - def __iter__(self): - return iter(self._file) - - -def echo(message=None, file=None, nl=True, err=False, color=None): - """Prints a message plus a newline to the given file or stdout. On - first sight, this looks like the print function, but it has improved - support for handling Unicode and binary data that does not fail no - matter how badly configured the system is. - - Primarily it means that you can print binary data as well as Unicode - data on both 2.x and 3.x to the given file in the most appropriate way - possible. This is a very carefree function in that it will try its - best to not fail. As of Click 6.0 this includes support for unicode - output on the Windows console. - - In addition to that, if `colorama`_ is installed, the echo function will - also support clever handling of ANSI codes. Essentially it will then - do the following: - - - add transparent handling of ANSI color codes on Windows. - - hide ANSI codes automatically if the destination file is not a - terminal. - - .. _colorama: https://pypi.org/project/colorama/ - - .. versionchanged:: 6.0 - As of Click 6.0 the echo function will properly support unicode - output on the windows console. Not that click does not modify - the interpreter in any way which means that `sys.stdout` or the - print statement or function will still not provide unicode support. - - .. versionchanged:: 2.0 - Starting with version 2.0 of Click, the echo function will work - with colorama if it's installed. - - .. versionadded:: 3.0 - The `err` parameter was added. - - .. versionchanged:: 4.0 - Added the `color` flag. - - :param message: the message to print - :param file: the file to write to (defaults to ``stdout``) - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``. This is faster and easier than calling - :func:`get_text_stderr` yourself. - :param nl: if set to `True` (the default) a newline is printed afterwards. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. - """ - if file is None: - if err: - file = _default_text_stderr() - else: - file = _default_text_stdout() - - # Convert non bytes/text into the native string type. - if message is not None and not isinstance(message, echo_native_types): - message = text_type(message) - - if nl: - message = message or u"" - if isinstance(message, text_type): - message += u"\n" - else: - message += b"\n" - - # If there is a message, and we're in Python 3, and the value looks - # like bytes, we manually need to find the binary stream and write the - # message in there. This is done separately so that most stream - # types will work as you would expect. Eg: you can write to StringIO - # for other cases. - if message and not PY2 and is_bytes(message): - binary_file = _find_binary_writer(file) - if binary_file is not None: - file.flush() - binary_file.write(message) - binary_file.flush() - return - - # ANSI-style support. If there is no message or we are dealing with - # bytes nothing is happening. If we are connected to a file we want - # to strip colors. If we are on windows we either wrap the stream - # to strip the color or we use the colorama support to translate the - # ansi codes to API calls. - if message and not is_bytes(message): - color = resolve_color_default(color) - if should_strip_ansi(file, color): - message = strip_ansi(message) - elif WIN: - if auto_wrap_for_ansi is not None: - file = auto_wrap_for_ansi(file) - elif not color: - message = strip_ansi(message) - - if message: - file.write(message) - file.flush() - - -def get_binary_stream(name): - """Returns a system stream for byte processing. This essentially - returns the stream from the sys module with the given name but it - solves some compatibility issues between different Python versions. - Primarily this function is necessary for getting binary streams on - Python 3. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - """ - opener = binary_streams.get(name) - if opener is None: - raise TypeError("Unknown standard stream '{}'".format(name)) - return opener() - - -def get_text_stream(name, encoding=None, errors="strict"): - """Returns a system stream for text processing. This usually returns - a wrapped stream around a binary stream returned from - :func:`get_binary_stream` but it also can take shortcuts on Python 3 - for already correctly configured streams. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - :param encoding: overrides the detected default encoding. - :param errors: overrides the default error mode. - """ - opener = text_streams.get(name) - if opener is None: - raise TypeError("Unknown standard stream '{}'".format(name)) - return opener(encoding, errors) - - -def open_file( - filename, mode="r", encoding=None, errors="strict", lazy=False, atomic=False -): - """This is similar to how the :class:`File` works but for manual - usage. Files are opened non lazy by default. This can open regular - files as well as stdin/stdout if ``'-'`` is passed. - - If stdin/stdout is returned the stream is wrapped so that the context - manager will not close the stream accidentally. This makes it possible - to always use the function like this without having to worry to - accidentally close a standard stream:: - - with open_file(filename) as f: - ... - - .. versionadded:: 3.0 - - :param filename: the name of the file to open (or ``'-'`` for stdin/stdout). - :param mode: the mode in which to open the file. - :param encoding: the encoding to use. - :param errors: the error handling for this file. - :param lazy: can be flipped to true to open the file lazily. - :param atomic: in atomic mode writes go into a temporary file and it's - moved on close. - """ - if lazy: - return LazyFile(filename, mode, encoding, errors, atomic=atomic) - f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) - if not should_close: - f = KeepOpenFile(f) - return f - - -def get_os_args(): - """This returns the argument part of sys.argv in the most appropriate - form for processing. What this means is that this return value is in - a format that works for Click to process but does not necessarily - correspond well to what's actually standard for the interpreter. - - On most environments the return value is ``sys.argv[:1]`` unchanged. - However if you are on Windows and running Python 2 the return value - will actually be a list of unicode strings instead because the - default behavior on that platform otherwise will not be able to - carry all possible values that sys.argv can have. - - .. versionadded:: 6.0 - """ - # We can only extract the unicode argv if sys.argv has not been - # changed since the startup of the application. - if PY2 and WIN and _initial_argv_hash == _hash_py_argv(): - return _get_windows_argv() - return sys.argv[1:] - - -def format_filename(filename, shorten=False): - """Formats a filename for user display. The main purpose of this - function is to ensure that the filename can be displayed at all. This - will decode the filename to unicode if necessary in a way that it will - not fail. Optionally, it can shorten the filename to not include the - full path to the filename. - - :param filename: formats a filename for UI display. This will also convert - the filename into unicode without failing. - :param shorten: this optionally shortens the filename to strip of the - path that leads up to it. - """ - if shorten: - filename = os.path.basename(filename) - return filename_to_ui(filename) - - -def get_app_dir(app_name, roaming=True, force_posix=False): - r"""Returns the config folder for the application. The default behavior - is to return whatever is most appropriate for the operating system. - - To give you an idea, for an app called ``"Foo Bar"``, something like - the following folders could be returned: - - Mac OS X: - ``~/Library/Application Support/Foo Bar`` - Mac OS X (POSIX): - ``~/.foo-bar`` - Unix: - ``~/.config/foo-bar`` - Unix (POSIX): - ``~/.foo-bar`` - Win XP (roaming): - ``C:\Documents and Settings\\Local Settings\Application Data\Foo Bar`` - Win XP (not roaming): - ``C:\Documents and Settings\\Application Data\Foo Bar`` - Win 7 (roaming): - ``C:\Users\\AppData\Roaming\Foo Bar`` - Win 7 (not roaming): - ``C:\Users\\AppData\Local\Foo Bar`` - - .. versionadded:: 2.0 - - :param app_name: the application name. This should be properly capitalized - and can contain whitespace. - :param roaming: controls if the folder should be roaming or not on Windows. - Has no affect otherwise. - :param force_posix: if this is set to `True` then on any POSIX system the - folder will be stored in the home folder with a leading - dot instead of the XDG config home or darwin's - application support folder. - """ - if WIN: - key = "APPDATA" if roaming else "LOCALAPPDATA" - folder = os.environ.get(key) - if folder is None: - folder = os.path.expanduser("~") - return os.path.join(folder, app_name) - if force_posix: - return os.path.join(os.path.expanduser("~/.{}".format(_posixify(app_name)))) - if sys.platform == "darwin": - return os.path.join( - os.path.expanduser("~/Library/Application Support"), app_name - ) - return os.path.join( - os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), - _posixify(app_name), - ) - - -class PacifyFlushWrapper(object): - """This wrapper is used to catch and suppress BrokenPipeErrors resulting - from ``.flush()`` being called on broken pipe during the shutdown/final-GC - of the Python interpreter. Notably ``.flush()`` is always called on - ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any - other cleanup code, and the case where the underlying file is not a broken - pipe, all calls and attributes are proxied. - """ - - def __init__(self, wrapped): - self.wrapped = wrapped - - def flush(self): - try: - self.wrapped.flush() - except IOError as e: - import errno - - if e.errno != errno.EPIPE: - raise - - def __getattr__(self, attr): - return getattr(self.wrapped, attr) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/easy_install.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/easy_install.py deleted file mode 100644 index d87e984..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/easy_install.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Run the EasyInstall command""" - -if __name__ == '__main__': - from setuptools.command.easy_install import main - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__init__.py deleted file mode 100644 index 1a487e1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__init__.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask - ~~~~~ - - A microframework based on Werkzeug. It's extensively documented - and follows best practice patterns. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -# utilities we import from Werkzeug and Jinja2 that are unused -# in the module but are exported as public interface. -from jinja2 import escape -from jinja2 import Markup -from werkzeug.exceptions import abort -from werkzeug.utils import redirect - -from . import json -from ._compat import json_available -from .app import Flask -from .app import Request -from .app import Response -from .blueprints import Blueprint -from .config import Config -from .ctx import after_this_request -from .ctx import copy_current_request_context -from .ctx import has_app_context -from .ctx import has_request_context -from .globals import _app_ctx_stack -from .globals import _request_ctx_stack -from .globals import current_app -from .globals import g -from .globals import request -from .globals import session -from .helpers import flash -from .helpers import get_flashed_messages -from .helpers import get_template_attribute -from .helpers import make_response -from .helpers import safe_join -from .helpers import send_file -from .helpers import send_from_directory -from .helpers import stream_with_context -from .helpers import url_for -from .json import jsonify -from .signals import appcontext_popped -from .signals import appcontext_pushed -from .signals import appcontext_tearing_down -from .signals import before_render_template -from .signals import got_request_exception -from .signals import message_flashed -from .signals import request_finished -from .signals import request_started -from .signals import request_tearing_down -from .signals import signals_available -from .signals import template_rendered -from .templating import render_template -from .templating import render_template_string - -__version__ = "1.1.2" diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__main__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__main__.py deleted file mode 100644 index f61dbc0..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__main__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.__main__ - ~~~~~~~~~~~~~~ - - Alias for flask.run for the command line. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" - -if __name__ == "__main__": - from .cli import main - - main(as_module=True) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 26a05772c8e4522bf615c48b8707152f168b7b43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2093 zcmbuA%~B&b5XWtd8EmkPF&LK5;Tr?C!MjU#Nh+1FsZ`~VRBHE-sy;*|&&c+G=3^xd zAA87qP_{gST!D(^SveP0p=!A#=ffJ*ESKd%xCo1uE68=ITb@H+f+fpU2hUF#XP1v-&EZuMmwk*Fu-iB?Rj>;7a8v@7n6h;(oxiwpPi!w=1u&3BTgS`N-u3^1K@>gD|axA1L9O&)K2(?qSO<2O8zyenyR{zu9K zg7aQ{Ofgy-{$A)L#0L~22)o-bj3T0-U2Fz0=3)mef_dSttP3b{G}%~fz&FG#)pi;7fJ>v z^x_aNshTFw9A;M)kQBXl)C}2*-SKtMY8DL-Q&=gy5~@UvoM-M-nVc&mb0k&jaQZUt zVj|Q$nQ9~pB#R_m(Z_n_`J+Cq7lVeAIu!Slh`Um0~y9VGvD+9pieNsu(t zD8UOV{O0XI2-%b!!9Skg^S1qeZ8L@k$1v7P?jNSV31dH%;# I|JRBC0Q}@c@&Et; diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__main__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/__main__.cpython-37.pyc deleted file mode 100644 index d0a515b3e3ea91ccc0e13c6cf8e1b95a85064823..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385 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 U%NrFog3$;@I{Fc#YL1-wFOrGs6aWAK diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/app.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/app.cpython-37.pyc deleted file mode 100644 index c4f600cc1ae6e0ed3488012e6c796d6153751bba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74504 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/blueprints.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/blueprints.cpython-37.pyc deleted file mode 100644 index e132ad0de007e048be0c582b9e4b3a584e822a92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22895 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 S`^<{i@rqrqg>qr$_5TCwaQ@{0 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/cli.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/cli.cpython-37.pyc deleted file mode 100644 index cf0ec60e9e9f4802acdddc689425852a8f4b14c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26205 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 #0~qk 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Ð z$o{=>sy0F+M?y0c4h{7*0s~las^;8BRt|8S$Ds%V$DPO4DT3P=+;k7rsO^KceA7nk z1GkY)or9))?H87IAA=uHoL|^KwKC_gYZgN=^s0q0L_|+O<52IxOo2)g+9oJ`6^1d$QH9~tw$YfG4^{no>*RFR%YS?tpHPQpv)%}t zwN_vUwj>QP_YdPWR6rH~fD^Yh*6jo_YkD=Zo#froZ?p@!;+;00;Qejuv%mY)nb;Hf z%c;*H^ySUNYq~jhbf8-U=fshJuiM<^-WP~;B<@da^|y!Dcw;6PkJhLh64K@V*qutq z(L?L-TDE4|SxBu;&DOR?TPMy`x=v-7TeTCgKeoS!0F?_lCFy%C#R@KRl}=B2$Pgc) z{t(AZ#J&>pVmJ!ZJmNw^HxBZrjx(38rMs@SN}sU}(%C*9*t+a4S02gyTDQ@$k6S19WC6lz0q|?` zCIs06y(N)#^s?@Z1Jlpyq+{v?<4*nV@ZTOZZ{xZ7k~R7tzJS&j z#~yEf-=cjk+U|@Or{CQKTo)%xc@t0K;Ni_R^JaPWX51hv zp#0PEk~vemE91so8ZPivs%ySFZ|{ zGF-^40Ivjm=r&3k3?SMBFE9NV+b)xh0XC4q(Za~TEhGH4%Vq4ckfA~ihm@-gt;inGyAMbVbsj9tdeTT}V=_ zQQb8~-Dg_tm48)B+<6zIJJUQzo`@AAW)d?ZN z(<}dy1nMzHNIQO>aFdcSNivLM-Vx*jeQffB7*~o_`eFHf#_kEh_Ou>tZPuBo-YAdr zyqC+}O=P#!=Datx`RB97K#uM1vZP>LxjG-208_Q*RjZcBiXqe~6e_WbB%iGokW~Z? znZ%l;JWu6O-k|c3sgp)b8fPa;+1(WqGy>9-Bq6)!Di;8$g4qD701*qTq?P;#@B0fn z*HIdpC6ez`i4Q@J3?w*81B&Yhcs9IBWS5D)4;=-p_7{`@Glqji z?HxZ)V&6utA&rtOoDIbAGr$ne#xq7&ia5)HQl)LZ4;l*`qPGr?RR#TO`ZL9(0WCIJXD_hga1hV7j& z+hT*7v))Nt?INq8YIG!}fmxgnhvf5QO60>tTxjfC1a`si=9xmOP_j{>4FR0(0#X;= zg8ln|%`&d+t+&`!BwfkO;Z?RXNqI-K}s})w1JbW zswuM16PY7r1IZ;Rf>+I{=bl+r6NHThx-?r_V+z4T3^T+;e^1sn;>TXb!Z^0)%fF#c zFV)$QhtzUF*>k`^O*;x<4k&p^%VlDx+@?EngMNGNCaU&==5CtrASGq|Np`8d&e`0z z$py;|YJid}W@}>fmvI+^5i_C}PAj-kXRmM46cp{aJb;DHVnfFit diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/globals.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/globals.cpython-37.pyc deleted file mode 100644 index 7117100dd6a6602b6e24eb933f681b441836e418..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1697 zcmb_c!EWO=5EW%PmKEDcb{9SMz@nGBsGZF&&_hrxip>`2p;!b>fC4&HV8pSlm=d)l zmBfMDL)}yVpr6nm=*I}X_0(VJsY6Oh9CU9j9gb#3lbJVfD83#JBM+A*zkUxpp7*CU z?pA=xm$>yWD7Y7UoN!-|+>d=?^^WM|K^!E(1T zeE-CJjdrOVqtzLRR16>};pqcaXv&ZvTS6=<^s<$RGL=2e+t z7O|o^u%c~hB`eB|fxI-pZCi+d&Z+{Nkp&Z(SvAcU033M43flJh_4)bfU8O0dC$i9$ zFpd>2(<(<=n9V`)&mbC$aVAxi6)5xO6}v#xbRn;8VRj`mL|~C3%NGLjDf@_c-g_Ek zWr@@^IUe}_-S!+U9B#2VO_3zGe3TvBC%835VZ2N716dR9 zEkpHz@l9t#ej+AVleM?;@f#s;$KCo#(jJ&3H8+X2$ExlaS=NJZtHNYCe5I6B^|MD| zpj49UdEJ`>&e^E3Uk3%tLE-h_{pP7%eEfZMX!7!~%*shsl$aLy_ix%J zRUh4BU)ejbiL>3g7S+K1$31A9vH|@m`X7VdM^B2|EjuzhE;p(VQE{X4)_8$#k815* z2JM*C2%{cQsy#I04i+4f_hRZNc%yOK$`M9BhH`+Oy4Oyi`=@osxnT0rWF vbw9P@nH3LgI?YiUevwOF33z2)+Azou!p~J$DM}}8IgYgI2zTL diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/helpers.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/helpers.cpython-37.pyc deleted file mode 100644 index 682d6d6e0f05661766e44273572b4675859d00c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34512 zcmd6QTaX)9dLGcgU;xZjBt=mYS87qBW}qcOisDMzSxPHjW<>5%Bbppt7G4>^pnGO8 zg8`t^4Gss!Xj3c2mhJ4WT}j1umE#(woOm6_iS0O!%MW?TLn`q@T#oI;LCUF(?Oc?L zovP$XRW9fI{&P;FF$B5mJY`5U8r`SQ`Okm;^WV?uOH)(%1pb2LPyfKBZzmFe%pdk| z94D{g6P$Mv2`^DfcuCJ`Buh#8c1n(Xr%EaLPM6a1Jysf%?@TEp-{Ylm`OcQI_)ax) z+xb#H$-2^wiS5bKq@0g6rnaX_Q*xeZOmEMWX5@UlF}wXx=^;7KHV$ncE*+NhT;s_0 z!=;DiJdg9ErK55_f%8X7kI4CCE!&YQ>gOJ2cy4&N_( zpY=}R`}5wHy`pypPb_%Xy>s3RIQxS4hIiik9L_FyFM2Pb)GOZ0-skcCs<+^M0pDNr zE_kot`!(-X?~C}p=)LA$#P_Aw6W%57@<$2pGN4bDF5~wVZxO#2<@XhD$$K5;7QL(9 zHGD65&aFgYx%;)ei@&u-HP|X{_>H!&0=e=*{4Xz;u5Gs){^Qw-d?4`(ORs`PKJd+^wDw!Z~BfpuPKP z?!vm?^zXFQtLF&-p-Csy6Zj%P(H|kaj88C&Lzvi1?gOH`$@a96WvctvU-v^d-0)q$ zdAqJ!O_H7b22R|1;Hplu2}HZ~<|%xrpqKq|+$f{e%j`E1lNeJ^;}{`^Ll`0ES^O9vW)H&{JQk)tOnA-~W^OOB zpT3*$Qd{E~#&q|Oh%O8bdaux#)y}%R-ST`l*l2Yczzgxn-g@p@OIbX|Fem-f*mDnH z?#kk&w_g8C;ci8B{7S{Guel3ron~#JQZyZ}xXKSZsu{RIu;<_Q8?81678pL|0V{3f2?=)M5G35ez>M0&h@IWm0#~Q62 z;S;Ib)kbW9WNfAhq9BeFYW+1l5M*&kWG0<-GViDY&R6c4WS3da#UVCQm}qL5P003Yfk52WEj`rv5H@v74wH zMi0n12PEyN&*Dln9-KLxQ8FG!anghSvXu*FL*W0z*Qua+11O|RXmgY9t2RNeLZZNDiaK%ypND7xSs;6>HOPIWgRSK{OLuG_3`8`53w zo&iVnYh+Qk>;8_EA!?&0@NBacx?n1|>z?lwfu8A$0qBG6h%oAB%VpMBE*Fxe9BV1F zrGt1o1_qW`rrBYWLi3xjY6dITvS(jJrr=G7GZDL-hppeGQYkdul?Yw26S$8BF}(i6<1 zh}UWY=NKV>ZLMCb`_0-eMzb2A3b)z>&9~g`>K1AXT}-CHZPd5?2E;@Q$ge>s05Qm* zZu{FUwTm*ha2uHw2fVNN7X}2M)#dtuU~Vw>mD?aoho3I!3VLlcA5c(OpiV& zslF!F?Y25DieZj(K0_<;F?Jpx)13=WNna@{RW$_kwQ7?DP_5Mnq>=dUDwP(guiiu- zx1p&371ic0xVr*z$t}S|M0FcrazGL*6bg3<$(HZ8r9p#ufX12yZ;ckzAhocdD-&f9 zgrhY=x4zwODNJ~Qzf820O%jkOAu7N^uZ?JPr~qp*`121w%nEkvJ|y4VRlm__xpPC04sIJn7prPL`2IQ0uetZ` zQ*`dB;Yu{ih&n$%fTf@jaj_wcCIsIA9fAHhB#==pievD8&yGUX4Zs}gAYa>|*8hLw z@&6mTN03K+2+SB1i!LSuRpzP(zPhmBo-KY}2Dk=3Cx7I6{5*+Ia0rKwAv}7?ZzlJg zFab_Rv5};Ka(G0OP(9M5oqlEuTmj!u{-~Wl9L?-=a9%A&4@J;Z=+Qy&0&DpJ9H@v;S%kKqRYyZ;)mr?0YXK&1g1UeA z*quWkC$1#k%hM_lYv8$e!0Ek2nEIIF(oxGFi+Y&^U+4AjOWeen2bHFfTJC=JA{gR! zn|v8uRKu$|rsXcH9nsan{&t|j0^cROfIlj^$_=egZcFDh7#U zCYen-$xI6WG7fM)?R;0fN7WS4(v<4wR$$=?K#D`qPs8R3q3UoP6fGb11sqCZGPZrM zye?1`91WqAqMoD9;NasUl$SW+BqssSWO~w>e4KE~{b;bQeegOTcn$~H1Q6Bx$-5XD z2xE9Ap!GP)#qc|iCiXxK`>9^yu4q2h-Ap2JtF`SDmC#mb?6^&z@}>&G$DxD`foW1F zsfvCi)-(sLDryTv-X*^#Ry#Q;RSU{r(OfpFw`D91SF~K+ZLMxX?|~8vk|6&x_fcWB z(ZLf?zGONA7Ell7D#;2;R|{<(sDz5}68#i_J@6ZAFkeEj(i*x1%}dp5TkM6@hF(DU zY4A~1J+!J?Bqj+9*f6FQjiP!Jjsz&ktu-UC**Gl~T^l4NrRYw*(Ex`AlI{U*XQN)* zkV32&%$@iIl~!@p0Ai%|wKc5*Hd-y1)1r<53+O(T6=|hPOBYY04^<4%j;SCnp~;M4 z_4;=X3cd*axT(sVrVSXz^K(+TxDjqQ=1xKCw_Z7a&Tz=Dpksu&+1lY)1|*OT>MT^0 z1hVh3VWYLZBI?#atizG<-9Z`X1|%#y?(j#+5PtvMyQgo!N~vu?p$O*Qb6;`iXtn6y zqGr`vt;R_4Z0j1ODpA>LgEpzPgYsZzLH?t<^^SIOaWrByOMTj{3PnUpJf})TTU0{t zROuvhYtZ)qYn)Owf?&z^UEdY7c48jSQfel57@BDK~Bpb^?)d5ub(9@WAr)@;Uf z1sxLWStzkq1v!GUh03A{0Ez>VL8&AUMtMUydRn6Nh>qSfFE!PpCi;KYIt?uah#cu$ zB&~w)sf&@RLZr?Y1~g%j@|UIufx_B*RQfs3A`Eyf@(px-tpycvhcqvg9~f2mG)NIP z8pPLtB&gE2t1!$w;XZ?5<~+4 zlqV&sGl)T2}nY7x|<<6+8p2M{6I%Be;#wVB>ahhv+Wy)k+a zywqQX9QD$WsXx#|)C6U2_HgGB$kyg0O5iz`fWnpBANR(*%w1&30SWge}7PRtp zv@$MAm@boL87ZHG%hTB#m-D=wXXSiC&U2_GyPu;nde?#SmfXwt@C0D^lU^qHgD~$+ zO0DV53Et_Y%M-iB?$KU)6Oi?iy=*VzO?@N1Hvttc*+czXxgSre>0X{Csn|7dq!Z!P zRvuSZlZidVdAetNfXo}akmvy_FNbeHTDS|t9#BnwF!^rcD~YD_ zE}k;2e9)Wlro)*Y`u#}arNrJuZvx8WO!e162Cr+QSGeO_H?Lc&6aUJ~vo=Hzc1_ic=z#gRj*?liX`&7f*(a)u9qLfiU9gz)KffLzkHwJB$mJP2h%1D6TMosAYmLc3b0|I7`x>S)|!ZB2+5@a9!$ zLT!W%Ac_cn70#vG+KFu?5Zt&btU-lR{+bVo3Z>2VPGnY819hY}3f1pucBZQl^I?Dh zBZ=TxbLZjPu2c$fPl9MUQ9IHB(H;hqURP(ZW?~hCPQ-aVqbCqC^K(V10zLr2&=Mr2 zu&bC?_O3lJ82z&U=Z7F#JdC}_<9zE#UU0!^|c~C->SO- z4Uk>sLy*GlQ0Pv&Cm@KHKnVp$%KC=8K%>W0Q6yreWLZj;!S)#%3*Z8lct*uwUQ3Ti z(~W@XDEC7QoOqsEQy#daOk8uL|fG zX(5*bGntC5%ozI2-l3ZhdOM$&*&#J9Ao5oQELsZ2!e159&}pp%76Bhrqfkvzsgi;iLOL>h8e5z1f@x!i;(Hg#|(w&>Ku$96F$OdswyHDtVDP0 zd%!V@VDLe^1;#*>e>$oH>ZG})CH=*wRWRd|jK%>yp_nao`fu73Np)eYdDFKFEn!NwCyJ&{W z)Cw24cVHq7gP@AyBvufBBKBlD z5<5dejB zqz_IeenautKA;xu$Hi#rN`PBvNd`w{tu@A~L{JBOg z2#^}blKQObG>k~nt(PtRE^uDc^+%$q*myBGcy%>sHQ;fP$3ZWVeq3~KNg&Sj94N)K zgZ~cC(4_`6twV{vU9Y0PVPy+0z9Cgjr(i(KfcMPQhA2MpPR?c3z{=HD5JG7ZXOQR& zk!pYK24{&YF)Gtn8_|*K43-RmEkJ4+ajyd|yH+ZBeo$9N@z=ztL+O&0O}~it#0);eVmJAUcv>0DMIlly&8?dbb8f?8db-WU}TzGh+3~fp((;qv@_E5 zkQo!^@k-^!&Bdj~n>QD)lrh%jTbHjcigGJ1D?Ym*sx%e1;UT!7f4&O%=;<)^9nf#d z!K$~b^@h%uxd?4|&3(tHjR>ebf0m=dLJV#hG5}gkZJ;aa1Be*F!xm{aJYY?0HM2-1Zt$)J+qIy5^NQ3vAk(9`Q73;+{^ zqg~o`udb}zFs7%jX}SCHP~5}L2CWH+=L2Z z|Besi4jmDVYt-XIBOtz%ezI7~MdZ2E{o5A@7KaJDz)_8qAGV?WR0hssJ2E}n0gQf*(uWZ*nBsn2CdU%TCJ4E%X*yp2STtpoQqtW}XK9{9rPd@~lV0-5(P|Ruio4sF4u7 zEtj=*rY3Q-FjdN09^cPszFo?oIfSoD8H@wI)e>u&j$o364?Jcx#(qX)PhCN=entaO z%C{Px1;$ag`(vVZ9PpX-#|abg^hbC!cpHbr^-MD3NF;1Liv(i1fpn2EO`?(*BBAwAHNydyo^u4VF-~* zvgzoU)MmOTsUwAC^<5NX7AIyN+}<_Sa_7MdE!`Aw)kZQfRmkjh_5~(|VK!pBo7j)` zkw!HM3#7*bit>$JxRR(Zdr14EGl%{aszKImuZ>yZK2eL5!5%W%kc+iYDc6wep~U45 z*3Sk+6cId_vtpF$df zm%M=B{3blp`n-WQ0csDem)Fj>cMw^Q> zVdyj#g&NDqThv$&ko>R$O7CZFf#t%udIVP_M;F3PeDdlT%cKKfPS4lFWzvlG3F>?T zB$=`*MM2gdH}xN!oMUqRTbzp$C^`y320@ihsuCVslH&JFNKVWsk7iRQqXcn^o)f0F zGU`N_+E06!m`!ILvW-EdGD>}%P*=mTFf+)4MCK53hcKBFL5YE(k1&zBbOdR^TzD~F z{YQ|DH##(SI6VwyT5^MR&S*0UFh2P--xYIUTcdZWqfm(Heyj;HP9CAzXjMBiMXmX$ z9VWUW8QtgsOCX?tOS{%UaW`q^u#CMe9&`OXqM%X*lRLDtkRq{c#<%VVV)h&`ki>!m zbWE?%9!UX7R|EwU0t+qDnqy!w>J!BDHpq6~63;0MPysW_xO)sAS%N!|436`4n5Bur z&G0B>z62l!pz6p8({Hs=h$JKdDOLj5jd&23fuIrXZ>M(75HkHw%ywW6L(fS~SXu%9 z2JC5S0f?7iZHvt!t=xk*nWVO_wlS$@;O-%t0WU^ocr7$B>*w5itD;V#TA&UL5pY6U z5k89X85&Cr1N0d)%+eGh!W13|5}A~KdiL><9-33E5FkWZ`;sCZ+(R)^2|`TdXMpcu zrd1brNoEQK8D8$eXkCZSW8g->7dRf)bymdTGqEdJ8PF2Cgc9{HB^ub1R^o!?5|I$f1-) z56-fL{DsvbD>Au;!^{CFG~1S>|LlcEb$ivTzWUp!_J5kbWUmnmI7U>Z>d-4-p^$EEfbz zM@9kgON5YXsS?LwjX6(Xjl@xiy6L2<;aW|Wvf$()d~*0)#wS=wVby4I534@+a!7U6 zsh^L9&^#fyB%cuLjhOk6*vp6MP3WGz{M}@5Mb5{=>}C$Xojqh0AimEGimY0bdwG`I zOEt5261fb>PGDYQR{fNe%BhdTiT%l5>Mrst9!<1=$VINREt#`z&H%X4HlT!3gkESU|5^sP>Dw;<>%4Zzhuo^!6BF z+3Yb}ViVa7I-BBZZ({$^yGW`h=u2wFPv^qBNNhn$H?@9+iUc)Izc@=O*_?}v{g z8{^1_&fbKSJ}#xRqn>PDMONoT_?gWoJ|rgoD|$Jx|K#1orn{FzFHfMCPf0KTgX!f7 z+<*Em$1i6xG7JpiGvUe2XL}Q9bsBw{>rKPLnDid@jv_+@c^c9mM;$}n$4q&?IoktO zAYa4*_Ora=J=~kwER>&tcP*H$Ug2J{|54B3_dbHo>DhZIlvAo`NBQfvmYL0$yeGCC)`gm0-v7M!By)B^2Qy$V zPgTE#sdx*zfR<|3D?qKLDyzDzaaLjs@R9W1D7X!(NFLT?FmeNpJ3 zTtQ*CIS#1Csk;Vih@T3^*0F-v zXeP*-=Bi$)1(-O6*jZ>Zegzhhz%hTaQBIhS2hf+q&4jQl&)rg0*Q?(76dy`k_?zql|WBrG(rW_ZK|ml?nPtD6?`8=uNlLE>)RRrzD8pvc13Y)5ZhcN#gL1ioJ`Y9;Id4$$5zsAj zodH53CL$XfubBTvM`dkIT7}j%+LW3oG=}kHjykZa>CF|wFo+uf7+1JovK8A|;YKrp z_7y9LhL>(&5>K>Z0ZUixudP@AHl++NlBVDh}I&((tdLB{;^#pffGS!m!{*p=93l&ASYD=6Lov0TR* z7*K_*VY-I~gj>Ny9k24n0sd}q4DHBdfPPSK6)){#X~?xVt=roe=XRQCTGZZXd(Emf z{4FvG+*~_U^x)rf6h#R{7lqZqHYwkRl{D4DA`(sto853vJ-i@tJgP|M5NeKS>w$0# zDUnw9)%YC5l&w~P(T~Pv1SB?j6HIehi!(JbIdP|@wuA>TjpRX<#S=`Rlv!26sMz4X zZ*b9g0JR!;ede<^8uv6ab&71#_&PFiT=0h zLnP6a(`ZnI8-jY zkPz0Pr(SeYqM4{1l4$oCMG0JJ&5^Q;d9sFxO(&`WLuk+)sN>%2FVw35r^TA6e%ZX^OT$MfW4^_`uwx=0GeDY9g-dHvMHJ zy~stcz6Oa9bM=#oj6p^PVi*pq3dazmmEsCH0yk1%vWEtO1cR|R8WI~by@_dIv3iVm z7uD!pVkqvT8DUjo%T;YnaUD-%#3+1JM<5wc1-fQ%W7k0H{O^ic9`S(jnm4Kl*0sqP zOSp|Qi^k__qzR2cu1VQ5b|`&iTK5HR%iGmEW$c**mLBO8qiVQsHu}(rAhZyc5i`cZ zea85#Ra~iD$Bol(m>UsQag+vK83g-~EM{c`_rD?%i}pk`5?QYsBAZ&bPJjo~mrAHz zN+z{axll+_&^hzlQk~#=xt}kW^?p_5vbbft$6_kpnHIJu2~TUgr~9jK$#y}68G%Lc zv`9aRG+?N5k$A$mL{5pKYpfU|#K)|})0M&8h-MKC1+j3n!YphEtwm~4OeJGQ)Qerl z1O|Xef}z#yE5+{15jdS@1dZONLX!JPizEe3jv;fpJJt!;PQTnAs|K}ty_8;F`tp^2 zroP?;|Lx{Pv6`DZ87MBVhXXquRM(h(l(p@3bN1{xwSh999v;DI`uPD4y7_^7qdRR2 zU-z5q;YQz4t1H-6AZvTpA2*YybV!?Skk~G z%#qNmXUk$12c;RRWZ3J?FT=ZlZq(1hA>Ga2IZcccJ&69+QIFbWWebXXV5u1#`gx{j z>(ppP_q1|(HBEx(kCCed{q!dG;nAxGbCJ%{&#uB&CZFu*EUu8IB^I9Kx2vnHje8`j zS9svw4*d)lrFwopqm|G8p|_fKURV@ebdkB5NE6f7$Oig3P{B5=udXj?T>TW(zS1-- z>zI2>wjz);lK|!V=@!IeKMU3))35K;Tm5mP^!0PNyxJk-?`N8;)C959k9Ceo`|33U z%EyK2DXwIcY&E^1)fahpYKZxirnEr^p36vIKhy54!ZXKRC`NF<(zs!R{S-3A6%(|u zdD)#d{b>EH%>z(PTrXuY_rwFEn61(ufAf}rSelh}n&k0jw*bWudw&As7~ z8&?#g9fgOGq6ZS-Sm|l48n_G+iVOVG;lTunm_#WTxq$knlSaz)C*rMt%+|*=y2sWy z3NjP>X|^kn^rJ}%dg92cHwYhlc_8r9&qV^`_Ze0Bbreaga?hzeA}e`BRVI;X1(ngBO4(cZX zc@!EWW8f%qMg$=ay~H{a6z;6{l2;P%m3{<4JNW!lNO3?e(#PfGW9F2a{d*=PlJ9STbcVbIA-kQf4>i z*$7Ay`R(67_s+F1Un?)YdHu@b&AIom;esLl;UzUuN zH~NcK*SsR!liqxRD`9SO=L#YY>b>k96{-B@fnw2M$f#}+zKz;u5KMMzT=DP@4yig3 z>h%+YL5Xf0ury)xM6H;bMBxt>2HH-v@DR&{^a8k`XxETPK6*S+L+dz03M1R5V1p-` znb**Fxk^yB%tFR7cIcAQ{lNsF9OEQ-ffIn~zlaP^GxW%4wb>PuB$`}~M~2mLltciQ zl3jBOMqy<~%ilqb5*AJ;y2m3*h{b}LM$N4-yH2s#O%;o03KRVtZI3$yzMrLRk+T$X zt@@MY78qiKEV~_u7*vW)1vrTGMdB-oMlph`-r<4M7|KE}LUt(^4M~5D-sV8}#lSBC z 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 Vb8BA1Ym^$z+6Mv5YxuSG?*S#vfWZI& diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/sessions.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/__pycache__/sessions.cpython-37.pyc deleted file mode 100644 index f558e96f3ec9b85ecb9ff3d4e226d12a869d3193..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12189 zcmb_i&2t+^cE=0`zyJhEQJ=P>T~CzVNJu0|wl=N}%W+wzsWr0_r4?xJE;b1;L^p{c z2N<|#K#B;Qq#{-A$$Q8xl}eRVl~i_bIixoKKrYEK$GPUTxuhz$_>%nI>zToTgl%nA zKu*s`f4zR+?{$B$yj&~b7aD*4C$D|CQ1}meNq;3gypJpVcNC(~E(k-IzR@=LZnjO_ zi+*uXY!?lxvwUk%YM1!Agy(X*%+F=NGO*h=o-4xktAkp*#?MuMX;5$1`MHMY<@Pc^ zFZnBj)%L1U_+CNO#q#rlSeCVebI*$HHGEkStN5}iZMpW$YM;lKb7Bo&*5rA#xPbTb z;sV|;$cuQtBv+pm+L!V5qPT>wm*gdUy&}w3p>cWgw>1a9J>Lxvo1qLtFBpdW>CfhV zHU73W82NG_hf(PCg5c1T&aN9u;iMgt*I?*)Q7GKuzEr_DZ0gSIy(7tu;P?rsmC zN?zFUMtE3`g2?qdq3i`i5#qze9e00Uia%^U+MbQvBdF3}5fAU<3g1B?3t)``u|>Nm zEn$k{^TIQuU6Q4Pvar%OQEFF2xozXBiVDbJ$Mu%R{X_4mH=Nwvd^&Ogfa4NIy`Ccg zKj3xMiF52l{S@Jj8%4_79Y->3_Go$Zqq~J`16No_F)h4czI{m)FHY|6^u5qga*vP@ zI#FLb-R||yNUDK51Z}T(yUw9Jal9ed(bUbjHmko6v=sMcgqsygfA1FswTfB3c>8uV z7~LLuqg&(Q2soGG)^T4-|Cax@bU%IP#J$a2b~|O3=IA7@X0u);XiXG_;^cB38O^Lo zkE_vw?u2$;;W<1+g{kq(m|~UhLQ1hpb6e5M3B=tX@EfLD!E0PPa{aMnaCJeQ)f$T5 z#HFV<@9%6kYO&qv4Bdh3bg=Z!AP{4pp6i{?r(@SoYAT(M2zvNzk5m9KqZ1x0E{8IT zq>76}c^up5?Cp6{#J1b(fyz?k03ggMhGGd%uM-pmxNTTwy|hxXN>)ixO%GT0BkIyG ze1am+a>8tb>Dnbx|7l?l+DMe1SKDQNE{n=@8*I1CZ?>qS#uh95RufBjtNs*h)2;z~ ztMP@F>_NCTSjZD+@ZDe6!$V|iyQa(eD?7(`%a-*b2U6DLv_-T~u*ua)ES z80pMldr-u=aTGQkIT%GJjhjvwILQ>K>SCOM>kUJv?PSdmCV_wbu2$T&PNd}c<42u%6Rd|^(Fsrk}`YA5C_ZqLaoadV5h5*r9~=;#uP zggJQ!-1{4-QY0b`gE=|JLDVa*2E)#HL^|>TUPEROqijrWFQ8+y)A5F0)af+e^@ASP z^j*qb~?-qolZ`k9MpXuR|1A@O|E_w z7#SW@v1UA8#sC@_krA1U#p2X>X(TAI7#r$Mw9=q1bvn>VUL*&dPAcw2s4*by8a0{; z+Hc{N1ZRe&Hy4AKjn^ZH=tuXA(y!s=EQCboFM&}lqep^C^({Qd6(RTBu@6;x8c1sT z39cECR~7*Y5dWWmi)#?Y6dX-$hEaW+fIb7?Z{urw4!&@Lk3L@4k?vd;H&}6ddI6q_!8Bqy8 zCOC$6a>cD+2sNkmAx%T}o0VBQ9uEVbz}dq{4tz1PM&58=>#a=n5HAxF9uX4A=0xD; zXU1QqYG?8nI~X~qI>*BdHfLA%$Ug(rXwg$p;^Z+LyCF>m$Xkh8*OeWr1Rw;eI~u{& zbIF?_=)+(DO%3Rr@zDEpjCxoG-Kz=xQhzcYlGnFM$V-)w<*NNKE*~D#{j?@5b!gd= z7NxbIX-w8~RBCelcB8(K3vZ%d3{`?vXjMWl0=9+qN?hvs(uG|g1*5ovftc=^p(bzDr3H&_w#%X@tmoiGQ4(d`ZHgsuuZpUu z;SMV<>bNh7WwC;LU95_8xG#$}aUS;-aY0-8l)yFpx)*2zW1?7Q?39gl z-1mBYl9|vsmg;aK$NSfbi^%=ZP6Q8-O~af64kNf&5{Q2SxXO!xf@pF7b!xWWg_kx2 zaXHLkAHzv1LM$h%xXGLv0C+{7z>yvTFz$_gCs_)>Wyon-5e% znaWVGdjO9cxIx@PKGH6{6;v+-O|J@*!$H^n2VBe}Pe4HO!GP}_N+3QVm^1Rn+M!SU zQ4d%pfl6@1nAlUnK+nsTd%c^GogQ0JUfPqy58^goC!yL2oqlx|&Vr z2qH>>v4E$(zV6&eAMHjWOYW5~g z1^EplmllSeX;_w%UL9<7NpmLRqn#QW3f{u`yrk>4SttPR${A-4n%2%}hrb~vA#N$u zCf81LUGq%yIVLNj7c-gmr4aEI4vc3M3mB7s+vv;QAv=Apv+o^Am`ZI7K$LmT1La8* zq>RYe&hST!1cj&V3^(9Ba}ihM=6O~0X45T1vl-XCFr}0F4pyDv7;~M*@hUQF zd8+&a+G`9~CaEpR&`=#+2%Bgu+QBR}d3rkcFN*J~FIigKO>~p=N z^3;50d{&$m)z7%?619O!sZeYx>W8NK`Lr1RoW{Gt(4}(|Y>j32Aym#2b^x?Mi-1I2 z+t0Ai+Jfi`_nFcwTC=nHOfo7t+4&e236`+6*=lV)+U{&Tdi4FR&CZ999^Tv9hG~R) z^4I{SYDS8i4*N969x|&WGW6Snrl<4`k|t0}LPnGsWs5H1*D!E!|G;su5j5G8Pd1-) zw(mXMq(n$I$|I6l-5E`90CY^B7$IbAD11S#ISzrQ4d(#|2xkrH~pn7kq@o<;| z62+@XV|4UVJ0myhH!PjxqF`RVOD#vOsrBLaX$Ld(Gm^9>1-$S=+DU4<9jkXu&5ZcAVD(-R`}|j~{Gp+}k15^5oH@9cYw5Wg~%kN%!1N^$bSpCO&yiG%uVI zO#-KV?)1pW;k*Y_CRRi-(K&dYMbICj{y%YP%TZonIdU{3WG|)|?enD+gElrNf1j%2 z9R;WCl%s!!Lj5QjQOKD%XBjdOsw(IL_-Pz1r9sM!K-w!itNuRP*?IhE`@xSFk|>AA zE2r?7_WOFw#TRmjN#XzR43nkFx6XJu3p%_aHh;DVn`f}7L;KXh&2X1t^Vh^-Yjfk{ zCoo22GiO;YG9+g#gKqi?NL$O{K!f`~8Op4$Rv1a*f_+HznNt{N*zaF7!oV2UThNj{ z-g<-W#QOvHDec20EIE%vZ8>Hp9Ab~1suq$_=#g!YB*q~_@Ru`ZhI-=Ib!;NIND9n* z6)hP2*4EDEA~c`o&a~|-AUe;TA=VIL4gZ^=`fIo|?a(Wt2mR=tX=lpLPtAjZx)>QR z%$Fqh#VgRxf_D&HY|$6)anyow{#)UF%Nor~{h%4HkI zmNq~YVGg;>sE1kNH?j%R#7QR|INiV?JsnqI2PpnN?e;TaXZY(-4i_gOlALTAJ5!4l zkpNlTjsMB33sltyq7q{W6in_koX1!jR~%-OXBxOB%69=G;z)xaCFx_2RJEg9X~ z;C)U=Palq$oSC_qb)I?TAZa>oB9_`y$9MQ-Fc2Y9_giy0ql`F|&fArU{?dI;ooP(Q z;gOL&pYKdwUq%fw)!Ar7)0xSCvU&f>X6vKQ=Dm%NI!`u#@bPAgjCNx4F-Qa(cWSIKu8?gfTGcY45Ddmk>LT3dJjPsi#BD6DAv)r zk}SgmAL3NTD9N=z`?$m0NV5crn=xvV1km1R1|X##atBK&mz*0X%_(bzlVp&2MVW~S zDJV?ymx&{hq>;0Mu;mwD*bbttbe}+q{ALcjdvS$wrV^3DDSFoP`T94Bl%%B!<;gda z*=DJOe9Ip1{GcJ-zm$fP|6&4ywJCKBYLOfx;|DfR5l13DOV%$+)Mx8V^01UMPu#s^ zO{u4Yd35eAnN5rpk=ex*y!LD)NNgmZB7cj`l|4?vy1QZExz7jCc7o)@Q#+VzpwJH(M1 z&Ml~S==<+eai0ou_tp2P_=t)vDjrg?O~ntWpaT;*U}vGiT~yEpT1clQ?5o%Ut{~*A z+f{qrw(W{t##Ob?*|wsVJzUw3caZnV-=O&J~aB2+iC0t013G;Ic%Pwv=%y9Xd#l>&45wFxAofx{XR3m9(iryT`Fbib{O~c+?N6AjwugqTocUxzVKxMRRE*>v4 z9u*8psSU;=u_Ns|P>PUJhoW$3tILE@@?Yq1&_NM3*3=5`pq)j#6Hy6Y%SbhrPF|Z9 z4=Ph@T4Jo1sl~KR2Vty2WFOYlfdL)INl5Pbqx1wE6mMnVKJDPRL8Gev2tdRYP5O{e zR>T()4oFikbgB(h&>o#mpQ|dmDLTv(m&h=Miuj{Z$>nDrQ>78cMIUcUGN9LJP{ZDwvP;KGKV5B3T8-54K zHq{*<6X%EyfNVx+QJ={|T}jEz{i7$`qR9b2<_XayKjznzGJg#TKP7;_?Q2 zrHyi2VYgU@v7LtSiViraJrs1bq}gy+ax(zLLtwL5P!cGj+nch>senF50ooeT})=LA$%D7P5;LPKO|C z$=OPK*vlb_<5@0QE4Hts=O~&ahj6OK@M&N~6z!nI6_9QK z{!*l(+7;TjLuQ!suq^Ctn-f%qA7<-}j$#Cx8ZG^uc8=lS{hJ-_dL_T20BIs}^We);kDHX(oG zq;4=LccGg9+|BA4dYW>=l2fumjz)2mDI!-zS>Cj1Ckh)Ilfz)%-5lBZ) zItJ<3Nqvy|P8xtTaMB4#C-T}8a(24;t3#np5@F^e6Hil-7^nGZw{@KA;UZ7eLZ#Nw z%94(SQIcjU9Vc-*SDMBXDqe^<5#vPNq?w&5y^4)0gNP)-tqHhD*0494Q=3si(=5wJ zWsHj`%hx)d&g=!fbL;jk`WQATTb}76i6fO7bwTev`C|C-@O~ne;QJq_1Ud7HgG;ec zCKr+V_CbWYx-~$!3*B6YK@sLb-Fz8HUp8KQtRX!>qN#mYyo}Hm8~$Uz58WUgEP3U< z@~?cb^)4aWA%7s|>WPEwtWg9;C6gjZ;Rr=TX3-x+w_w-5x6kb&KhNWQxJ=<_b0vqX znNrCxxueAMPuAkxVSipBI?C5YSjwju84pFgO@EtORU|w^P_#M6fSeZ{&KH?nCMb6~ zf4&q+xuOrifji31fFySLUIW3!XnSrR!F<~={kzc3*D!2hL%xykTwLmqOQw&PeX~|bu{`FCmtaWCvSLT=rY}5PNbEviV8XbkZA<;G;|f) z83jgB135cJA$8-_Dm{Us!;-KR=#s5~Wh#|%I;Gj<4Of>ITqFs&jFZxtNVjg3)|o~o zi*#*gxK$-ajVOJX8mk15d_rZ0`mF&NW0;#Xwp%wYz_X>X6o`>&JQQT1r_1u*h*W|X zAbc4jE`5)-+xPj0#lMdQ=)(Z)Bb>bQVFdn`EcA5~R*Dwqz&Os&8ajZvQ|b^Uq+mH< z$&oK{8e7iahnYcJ;)UMkbcf2L+9ZMkxrXIJ`4M!tr;6_URw0W3ax_IaU*Z4TVc~A1 z@&nvn(|I=_F75?GBNwa-f+f?J}hzsH@W-GGPUtSeTfvPF+7IY8gYL+nI=d6d;}{MfWEgG?B?Uv z@qQj@d^hwV4w#DW;c$e*00+E$MJvkER7I8@Rsw$!3)ZbBN^+aAcdc4LqC&^Xn(wW2 zWNc~&gPAZ~t4PH!ls0^lY1Z4D?quS4;a&l(?hWXUW9??(cY=1K9rnGzgEs+JHvha~<2dFrNj~!6UQKAU5@iQoqLxZ(>W$j*8wgm^EFTr6IIF*9e;IJAT zUV+1EaCi+4tHFUyE?KzOtCS%);LU-RmCXWN+9*X=MDrWcwGno~eTb6H`MBAWk-%+#!y5`qF*H}HSZ#Dde zq8p%H-&M35H@8}TOVLfxGyV+d7MuCX@Y|motj%V>GT1D4-r2s5?>RP)?|E+FdzLM* zQy4eLPO~$3&$C5#7VibN^up+Tu>ZT3ho={Za&tN3Tf;caqNJ}He{n zNiW;r-nxibpL<#A{Uk~T;jLvoYNeYF--@Wek*#>QZhmspdmhFy&!k#nC62m0k$lB_ z@Z!<+Pp?0W!;$2zuOTg?V-~Fkq2$lfka2;pna9aaB+`Vo#OK0GeMr8VW>3;l!oD{3 zthpc@4ufvC7sxE^Zer-^K=ADmm)Wt_rFGs*1xH_k4T6$qj`61^blJyQmrg{FU6zM< z%Lk}3V_=Sr%tCEO#@NbDW^OjcN4Yt$bBkGbj2xOq%iY`?|FMIw(Qt6*E+|QFUy;jyaH?Uxyg+E-bP0cSFph^IxCc z$hL+zhSBi)C>cVwoL%4D;5@z_-{Rr+?YH3#g`XQG8^F)<@NIE1V4A&3#!3$rYiF^v zJdMh5>So<^OxJ9w(lW&@bH!Do9cL|9F*( zP3gtaCig;5@ct+cMTt+3AHm66A7$P~C_R~OVI*Tw27!jL669u*?#7(3o%Xzqbk}=A zHgZLJ>+y&WMU-UTuG&VXFoZDkqRi`t2~@|2fEF2tS|^bl)QzCe-JP%$&NHXC9wHxGW|N^%aeDNFtL8C%RfdyI4f^F^Y6i8PICmoHO?qrbqkCxjW*D&=-~?aH z8hF>4%bIvMN^k3GU+Xv79Ar9QEIo?kFwD9ez`XK*+HLK>x$kLlYG}l13OvH?Olvw( zkbp?x4dHatL>V&Nq=L(Evcj0TfAO2ysdUvP5z|9&lCs*FWDeg3kI2jq4RJ0v4&V=S>kwWJv^}ALLI2$2 z*Uz8bf4UmHeEd@oFCPcbes=%S)78&Ajz&}+F0dE%i?czWXMs#dqRRumhqx3aoD~bx z&Am`&9b2(i%uLyJ;Z6+d1j9w^Xwe_x)RJ7G0dTg>{Y&rR{b)wTeG`+YDDM9PqHm00 zWn*XW4fus69-5DgU#-5e#{*+mKs5ujP%NeF#h5UVNpq2xqG{Mplr!ka#_}a{HZ)FIu%JexJh$W>#*! zGk*&Q2^83?qK5M!xLqn`c;t);pnz=Ea6CM2uI5DJZdGW_>Ev%4kx(3h!HPP zBn4!{)SS-|G_U*@ypkQ8Ew|dqu0J^=8>FdBcGyvKQ zV>`Ez)J#TR&5_RNaobk`!P2$Z+F0AiBZmS{6&@u_TJcY;E6o?ps`G?lD#`tlPD|jR zfPs)LND8!u5)&+>6xf`3 z+S>pAdxUoU6sw(a3gGm^PnyvtX90Gb2OmBkL%2QtIxQP~x@@9}> zlum8z1-PXJQ+$e+3W8*M#HPyBC=F7#1(?*pqG(9a$#5qaSc4j%1OQTW7~r->5DNbc zBu_XDtAxSpiF8Y`R&lJ80&h3UHdIGH+Tn>x9!hp6cd=n8Ld-3bOr2__aPxrOikdl{ zqfUm=m2O?9u->;mT8f-q^N`;l0Vb;q*JEBDtlZV3J@obOTUS%(fgWY%r3v@=9uA2p zg~j3+=Rwv?I^#_7xuQ8M+10%4gd(Et2?xl^8+T>aK{;RHp=fINh|I)aqBH_BN9v5rTs0o|uCtRpj_E}Z z5DOa@u_@cj~6Bx?oLY`F`;JU*Si51~nt(o_-PwODC{UPW=;x>eRMLkPwvWu69l-*Y4L9C~pZ$ z`PBtU;P0z4&1>ijq0}&^e+>MF_M}odPUR}q~(T8+09`DZjW6( z;~ux&TXttMot_03MPVk^GtYoThZ z_|-#gsN1?K+YGycHY2PKYj#bvRYGHE+NP*i!}_pcH&CznX1FwL+D%cfhs(nidqvb6 z;kn_eeO^`GQT!#p`BL$ltTI>|TzH||7yM;^<)va@MBh1o6@9DBMElq9eBNKf^BSw+ z`88kLQCb%!|JJZ@^+Pu~Xs0YmgJ@5*d^~?OMAL)eC}cwxrHMsvTFH1cig{}7vv9{JRBt+jaFPF40I*GiGnE*0>##R)z*FU$4VcY?^j;d zZNsnnHEdPo$BLoYRcuE+TiKF}e|sE+KI85`>xyzWvN|3%DCzV*K4ko0!p3`IuiA?* z_pVv#zMER9d%zOQXMJ}ZVz2r<9-@Ou_K!y3mP>ptSc?U_L(3hFI@mvE-6v6?$KpLJ zjV*AnAMA}eBSP~VB&fILHb_DvH{I`8A8fyGQO(+AkSHtXBJ&qs-E|Y@falma)WkQ3 z`z#*>Gawm~-zSVeW&Snma6j<&#b_k8y&etG>(P6hg;>>7OfYU+5Bfs3_V65Cvv$GD zR7|w|vg5m{+vz>p-nzfFy}fnM!F-*a&3CuHzXdM#ddYa#kB4p$^?KLNezdc-{o&TO z)4eO+C3()N-F@`v{Rf+OA3u25b+#WqeB4`DY)P_X?G)6l$Q{y*iQNo@P|In}53)dp zL^SdCp@*O&e(5X7JCrC%nd@6||Llxkxy%KsgCveR#I~GeDJe4k!S}!og9&uhO|18J z9(FBS@Cd>vn#z%SJ>qDu*S7A4Njww2UQZ}rlsf6rh+(VJcA$z_u7 zB^@h<$Z=~FCjm*V8(J>k8%r~k&ts0}|4mUAMmabH!E&4fc61nXEcgFukk8ePu2&V- zKvA0brTRJC$$z4l>Pd5I;I8niQ{7h%>Zvj{Mz2pRFVq7)xthX#yik9niawM7Y^n~l z6W!NN)zKYaKQ`&vH!ds3^{K&azj9(sjj4I6p{D|BCJ)6MRlHG2D^u--dff1917q44 zR7Zb0t>Cvd`ebTO>nEmfo~nNRQ~g*+YyDV5+2B7*m*_WbzR>tT`i)5QmyVaF+Elb& zQr=YXo;p>W<#Z)IH&tF}gH`nEeQjF(8*N(qi3*3Mz_K;FlkaZ25m|iNG;6(7hjlCF z*7{7W*R8_~9@`gRCG(TlpG(y_ z?rdy4k5~#)#~aVdh#d1JY)4Das`8DjD!Vg-dVfLg;H}Tqw_4{jV>gb&Y~?OAfRjLO zaUS!mDlKHD@3Azi_G3PDQ(nPWe3^Nau8;ZGVV_xeJ-o%- zkG^x{ZV244k>iFoT=cJEW*fMZHVUQDRI93{uBcVbR9Dr8W~fcn8n_MB#NUcm)vD@6 z`c)^F7TsC9ShlATEnM)0@RW-3`?!SYPsq za{pl^lh_N~0__kzAWVtKyf|`uj+h|?zuWD$Y9wgnkQ^s#IF5vIs5c$w zBjB~Xr{*|*>^Y9uX)#o`oXd>I!Vn$hY+5S+Ce24oiX{0mO^R%wdC{mSD*dhex{&b_ zJ<(Rvv>(!|zl0)HPSh0G>4kc#VvF^uGF9^p{)bJ@z-er0Vf7ba>{)b_Z*jW~?=<2J zAc*-L>t_3A>5!h}`^?!e2HYT6daHe-ZEeO-Q4VxkzS--22W4M zS|0+OIixTSlSt1Ycmk+*wY5$jcQ!ZSX$#T&(kWT%Up15UFHWRoWF|ab1ldh8gKF8@ zy__L1XHR68*p-&XEo{N7ge<%Kr3=}mtus+5H3Q0TR`@N{%N?c;oeEsZyC@d$v1S_r zA?v>J(zGkA>R0^gOXY=X*C-$YS~mT<-@tEOhCX&fpyws1{BpK*pTMic^X@&!(vz4U zAPxx*NJ=={8;35pp5z!>Mlqg1{{V>yWPov!7>Mj3iVs8P@8PT6cr3SlKR(Q{G4KJ1 zLhqrWKqf-_L*_=~5wMqd%;7E>1qwW1V_-dVOCe;4z#iUpVFAcIz%=c~{t@6Ui^_;- zt`pyk0Eq%LqRG)6hhtxdnadW(M)qpD9ny9=vcj&tb|{M!Yqapl5xOb zf-n^2DZ)C?_4eIp56aT9ZnSUSDwKe1mk2}PF(`n#+5!-dym0Iz`hbGLgcUe&K4Qp0 zyydwOY-&M_UUvH_*eTs%3L8o*${G5qv0(n7VtBux(UbFNmx_g;qF4+9jKBkH5de~w zVN=5(k}6L7*8z7rz1)xWEG&40xk#nG?~(VXi^P_0^1KOI*;Gm4eE@n01i|kB>>%n- z^?`9o@%6vf0E_^`Aeu&ZQoniYO&Ak!a8fVWzR}X`rR}ZnKYYC9+`V^i+dlX1CW=oEf?++R2`9B^IVxm}8>#5_dvy zR8iM7O`Tkv)1I00Ef!DssE#|vo%|~bxLqt47;_CM7041ORT*eNkAzV5KmiIh=pDkO z!gf~%)#J)kAJinX{^HM$t9UYxYt!0EeX38ZgN8t^rl7hHss>R_D<@0S3Q?Fersjw6 z8c#4TTAQb+{}34ZWcid3aP4FT*jG({irP8Q1FAjMRR!2~m1qynp91}g8Li3ZDaMo3 zexPiFl25>);{GKWj(JV=;^A%(6<7e^^i`?}#V5f+9G6&bA(8+R32Bg(ayLp`k>4ot zBvJvSxkKpqQbnRQ_fU=i!tQd|M1FF zHypDoe`Nih_3c};0Up3Ma>R3Rl0~?QOp(km(bSHty;uOOeIAeZi0QC_$RxQOAAk|% zcxSCGMW{g4;7dLO81~4AzVE>xk3*k)tT4c(9Yp?rsPJCZ^OMM=~V^xW`76 z_abgm%svYb-5FCmLx$W(?_=qag*Hh8StgOBKj_Ik28giIKbNa1Vp_RsX@ZEO-AQNX zi^2qni@-o~##k+qVELZK@j-x9u!vUUx3lwweE_iGJb;Owyj74RAs~MEfiKb~B*Wl# z&OE@MeMa63OP3&b%!MknF4zrEjN=Sko;8tBOM@Yk@z4^SLy1jN&FA6MlhC$i+d~gIl5R$&@F}q3Aa`N`9mVbfxY@F<8`Y0Y{EATlZKs6>q z82en1IMEoGH2=tMChk*KKCL2D6SHylkv4&+%W653>?WKxhqj9D){?;6GixftuQzE? zO*j(9DM^U@V5WNfcWGe=(h^`Rnod^BiO*oMz{A;vVuf@1^ym0ExrRbnYXCV>Xw<}C zl>#W-Cbc!Fr=d{@)j%7-{jbfN?N?AO-4|gpx&^lWZ&YOXglvMe+HhH-Zise6)R8kt zK7*43{`M;e8vl%fEFbv6_$1s137e`gIzCtTnP2%3v8`o{IbeT<&pg(uBPS<>M;+ zfJ2~eQt@$SP;xt~jz>tLF?)%`G8e>b^$TN?F7e+XVihlp5vNkLlo_NPE%U6PE>4Pn z53ky_Jl;4Xko*xk{{^><+=bvZb;RrHYY?_I^`f?-HH|e09ASkf+6dgszsc&n2+~wa znIi^LOt(ptDW1dbAstfWwS0m|Xv5Cv-O1PU3{f=a=7Q)c@;!tFlgEfhx*);7ivo~_ zqTn;Dp!@}(C{)t<5A@0~1j=LLo_uY7mgRdMF_13G)|6Adfd|SgILfncrbw~@${3WM z<8MrjfllR#L1Oli`3N@&9+seW@3$&)ie%t;2ZdcPw$K+Mffq#dZn9^d$cbikstFgF zY3Z)`=T@R{X0}r7mOQAL{QccB%>NjW1h|Ei2~NGeSsdo{EQCS=8<4Me zXGa-Vq>tWw{{dXs5a&QXpwr`{5l%t~et05}K<85UPB`K(_2d}Y;o{^7sqP(iCUUrr z?mUIPkhIdl6T;64fq9WHMc@ESNuh(@hlMNiq-wWiNdF>m|A%;A;Qj*Ai_G6Q&{}NE zBBY0b%+o$3@Rt@@SYrCFM-!rpwuo*qxqGO%uZr}{ySw^MBvmiv`Y zDIu-hh7(AQPiPSpg7irG>LN8$b!qhvpt*DqM0FZMVEPmDA=lyqt43t#*aQ_yevKa6t_QbJ)FeYENc|wBNGnas9GKY+D zG(rHVNF)~Uk6%E}X`QK)l3v)uKeHxq&vu32}!r|I2j>^WMSL7Cyxec@g*6j#Sh zQ(jJ#;(RfKHt6=OJ;3qN43{pP)w~}dKtaqdld2*~lJA>@k8(y7R?JVDvvkaH{xnPE zozd`Zmf$F}moH^Dc9*vxvmWm9B8PJUw+L)WieZ2SgT8CPIW&6ozkB!qAr&0#BSm=9iuTQrWR!_Kmzm+?Q5U<7y8ui%r2L*MExy1PpILlS)DGQl9pfc_3gc5^4&w&K%ltIPr-dULqJHS$>pVYm&uX1L z_BoWEX+Md?t}^5AW>3R>xIc>W053pSGJlZXq&Lab7&n}HIXnYAoR)F_e| zZtgQZ5G+kV7A5S~c93kP?VML9Oh@}N+8XE%`{>HmE9`C%$3o{jcj71%i4q<5>AhR4 zAFtkwgRv5gf7wt@%g&Z|BR%kkLI-AZe5pzCcr298+%2IqZfT7|paDw*J!)vbv- z8RD4*1I%#;s;p<;x6ohkqi0#`u@*83bo4~9-2kdc84h7|#QNhTG-94Z>oskFWMgn=90{ zI%W~g(Nl=SK4A}=pWnXUd^B51(_Hk~afPiY5%({%Bp8Zg%xHxadMp#x{6fTW$}Xvk zO?Ju9&KL)yQTymIR+?)AqF%d3Jg+w|8{7J1+fQ=I+kx`Q7%R=;KK(XZt(@J1fk@bX zItDNjO={yJOl6=23)mi}OAS;xRn5Zwk2fC_zyHpg0= zG~hiEVxw-G?TQ?4xu_ zaSO4Ej(TJwj+BN+!8{|N6(ophEa=0*SpZjnJ&XeXrybyH8!4juRx@xF|jwR$C$w1g|_qm*MB4ncVo%3MsPE zL%-B+qA5yO+B&qpx4Dhr<{bRvUJyY4kmuQ7Q{$4vkz%L2=zFK zkKr^-xqxQ!^pZ0;7S#~oN)~j~*Mplmy$NgxF71+V1Bu}*)O}|fP6fX$Wh(L6qgWsp zaX!=idu>e*M{A>Kv^q{kLAWFMDr_m@)%YV3JpS!|ux4V}8u^!MkM^_W-yMte6?;L%- zWj$JW>P@^C&Y}H-^Z4=uYhq#6Eom|1d($=etzcZiZxz32u%a9M2?oBICa@cl18FnI zOq3uF!PDPpA_G{80|@r;LS8DlOgbl%N@DU~98(nldrmQ^5aY@al^Rzox%EMur?p)Q zd8i~b0%Syikp%4+Njp8#Zx24mM1TxfBt*#0O)4z8nI(kCH)YQPsbCW6A{r1t@4tqw zSzbF98%;3ir*b!t9A1?tzH;Lb1&5a75a9%|b*AGPHba=*JOl)4zd}>LK=;Dgwq95- z?7!Ggor$vz08H=>!`T}xCu8q_T}^WY39Z+0NcmXZW2d~6sJ-%Ks!?>Rx{ z5r-W5%b=C#(LF#@C|Th93--ag2EIiWXkUv{)EDZyDGXb+tT78nS>5+3_4$6*@cq0n z^nG~-e6pJF^EAXvt%&m3J4HR=2VhF6l{^mWWUX%2pv_0O9 z?dexBbVuvW=T;x#fVKdpau`u5zDwi$2)X|gA`Es>HW5V*)6f6{Qq|C=F-uJ_(3S=)51p6J#GW`4_mxX` zl!?1jlY81dw4QosjP;Q+Yq{_?6S&uges#|lkbD4B$v!8l!aAh z^PGi8!_3_g`^X}5e(s6Dyg`BSr%OgbFepLTvfpy*cGYPBip%I5_L-_@ADo|=hm6>s z3g4>E5GgNWc@9KknJpHZg(x|v8`7>VTV5qfvpMM^MKjJ^cRj~w=QY4l7P>(s1nQ%J zGhnlD$?>4&O4gXk7+6@ee&VKA0IRr{09eyNTw*J~4xqA?LXFadqxdv9Gfp&xV4Hmg z;EKI~()48(^-W<^-ho)adOeu4*DDr)MB}c5^st%N6_k%C0uPV?P&M~@xDbH4kVduH z$-4ArI;QNje)rDG?3l+2MY=;^Uvq6ZHbse|D4+ojh5KcjD4Su<7B_(_MWIiW^bj+; zmHr&Jg3ZH{#Um8GKg*l_hFvX_O};@XQ1k2GHUI0KWhNx~eSTe;>0@?fnbP6TLR*w2 zB83HNUlWM#qSGisw7u=TbYJ0L7l-ascj9tur!KG1S8ne(cmoXpHk+MOpJ|V~L~+hK zw7*CApkQJ$owt#BU))~5C25<3^WP*T7+~leTNX%onMIEH zEb%(Re-Ag#6FOXd2`)-sHd+hD*O52Fbcl<-BtJzQi_=YH-~5nsxXB;T|3$QH w(QGx{+!moWNhR|%B8hQ#!|+XeXZ34&lDYv`I%!d-TSP0z1qx#k6u#7P)Y|JtQsIIR8-ZyxRo_IvWwlkm>34#z)kD9< z+x|+>xB9Bz@mGU2YfabgYrM;QFE!p1y_1I3#q$d9bM(R zf7N)dzt&ImZ}rqT(Y}R9h%m;>kH2s{UvQR2j0-p7f|0%~Iye+AO!D>hZ?I7Z;_@aJ z2iZ*0K6z^z$-qemMs6m;pXR#wyCzrh=07*K(;(iCy?84NW5-@+EGSx43RKxB-tD@Rnh)ncDm6B|=WI}sEj;w{0>R(_e zl6`uBBOw<{kT_?Yoc0`}fBC_Je!l`}n=gP1|7iH{_p=<+-CzHM{0Ze(PI`qYUkYu&{Xocb1J$<=R8NOQi zmbq*E|3ztTd5!CZu@^0Qt?0c18*t;b!5b>dOt_%A{Fq!o@K}X<$xZCQ&qOSN8o54{ z1jdrWc06dvAJPM9n73pS`(AqSA@Xi5;wwxpV`x)fUaF2#zpu|iSwZlpGUIb}QtcJa z@mkll)Q~q*}H#tt^w}SRJnDrd9Pw=Z)&Kxf<2S7MP2e3!jP?`2pr2|5U{9U|dF3Otgm&$$n0?bUTc*)(^?Uu6qAV9L>PrCzo|5aho#RHuh*ndyzSE|<;=~U4 zvHczD7^{P@Y)e}2`~%@Y;aQb#WpRR(15f}E{s$R8j^rX?zPAvR?J70TN}0+iI7M@S zJBb7r5y{M*rvik)zTAKKfK|=~?;tIXxf9L=AC1^&!|OFjs$w(A;y9AZ@DAs|R#@## zbw8~=Sd|pRk_wdbr`aj!DpUqPQ=pTW895Rsry=J09tiE!3Y5N7;E)of@!q9xt?+H7 zU}=$p{i1~@?8IA&66crQR6I+!=V{=-Rh`#dPl)kcd!@am8eAU(gF4Vtp-G7kdD8_X zi8oS^vM=AXt9gV!s%HKg;|WRD^yP=uXUFjTyc$~xzA1~TB?LonR~@O5Hh`VRA@PE- z{M*IV$B0ZfDoc<@zuUQI@9kLk-YP$e&npV-Jt684I$wbisMdO)H7LlwwtQ7_eUdN$ zTv<(#d~3ZZbZR{YO;zN`%Q#)$M05et2}$zxGxAHuf&;pC5y-&JQ?UCP*1SL~K0?~2 z-fJwczDw6Z_Y4xtA7iPtQNn~>!H4`Qh9#pL$J)3LlODb>A{OG{(lfvlAe5W@Rx1G<6@2p?bzaUhpYwG>t&%keEqqn*9UocgJ AJ^%m! diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/_compat.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/_compat.py deleted file mode 100644 index 76c442c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/_compat.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask._compat - ~~~~~~~~~~~~~ - - Some py2/py3 compatibility support based on a stripped down - version of six so we don't have to depend on a specific version - of it. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import sys - -PY2 = sys.version_info[0] == 2 -_identity = lambda x: x - -try: # Python 2 - text_type = unicode - string_types = (str, unicode) - integer_types = (int, long) -except NameError: # Python 3 - text_type = str - string_types = (str,) - integer_types = (int,) - -if not PY2: - iterkeys = lambda d: iter(d.keys()) - itervalues = lambda d: iter(d.values()) - iteritems = lambda d: iter(d.items()) - - from inspect import getfullargspec as getargspec - from io import StringIO - import collections.abc as collections_abc - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - implements_to_string = _identity - -else: - iterkeys = lambda d: d.iterkeys() - itervalues = lambda d: d.itervalues() - iteritems = lambda d: d.iteritems() - - from inspect import getargspec - from cStringIO import StringIO - import collections as collections_abc - - exec("def reraise(tp, value, tb=None):\n raise tp, value, tb") - - def implements_to_string(cls): - cls.__unicode__ = cls.__str__ - cls.__str__ = lambda x: x.__unicode__().encode("utf-8") - return cls - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a - # dummy metaclass for one level of class instantiation that replaces - # itself with the actual metaclass. - class metaclass(type): - def __new__(metacls, name, this_bases, d): - return meta(name, bases, d) - - return type.__new__(metaclass, "temporary_class", (), {}) - - -# Certain versions of pypy have a bug where clearing the exception stack -# breaks the __exit__ function in a very peculiar way. The second level of -# exception blocks is necessary because pypy seems to forget to check if an -# exception happened until the next bytecode instruction? -# -# Relevant PyPy bugfix commit: -# https://bitbucket.org/pypy/pypy/commits/77ecf91c635a287e88e60d8ddb0f4e9df4003301 -# According to ronan on #pypy IRC, it is released in PyPy2 2.3 and later -# versions. -# -# Ubuntu 14.04 has PyPy 2.2.1, which does exhibit this bug. -BROKEN_PYPY_CTXMGR_EXIT = False -if hasattr(sys, "pypy_version_info"): - - class _Mgr(object): - def __enter__(self): - return self - - def __exit__(self, *args): - if hasattr(sys, "exc_clear"): - # Python 3 (PyPy3) doesn't have exc_clear - sys.exc_clear() - - try: - try: - with _Mgr(): - raise AssertionError() - except: # noqa: B001 - # We intentionally use a bare except here. See the comment above - # regarding a pypy bug as to why. - raise - except TypeError: - BROKEN_PYPY_CTXMGR_EXIT = True - except AssertionError: - pass - - -try: - from os import fspath -except ImportError: - # Backwards compatibility as proposed in PEP 0519: - # https://www.python.org/dev/peps/pep-0519/#backwards-compatibility - def fspath(path): - return path.__fspath__() if hasattr(path, "__fspath__") else path - - -class _DeprecatedBool(object): - def __init__(self, name, version, value): - self.message = "'{}' is deprecated and will be removed in version {}.".format( - name, version - ) - self.value = value - - def _warn(self): - import warnings - - warnings.warn(self.message, DeprecationWarning, stacklevel=2) - - def __eq__(self, other): - self._warn() - return other == self.value - - def __ne__(self, other): - self._warn() - return other != self.value - - def __bool__(self): - self._warn() - return self.value - - __nonzero__ = __bool__ - - -json_available = _DeprecatedBool("flask.json_available", "2.0.0", True) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/app.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/app.py deleted file mode 100644 index e385899..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/app.py +++ /dev/null @@ -1,2467 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.app - ~~~~~~~~~ - - This module implements the central WSGI application object. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import os -import sys -import warnings -from datetime import timedelta -from functools import update_wrapper -from itertools import chain -from threading import Lock - -from werkzeug.datastructures import Headers -from werkzeug.datastructures import ImmutableDict -from werkzeug.exceptions import BadRequest -from werkzeug.exceptions import BadRequestKeyError -from werkzeug.exceptions import default_exceptions -from werkzeug.exceptions import HTTPException -from werkzeug.exceptions import InternalServerError -from werkzeug.exceptions import MethodNotAllowed -from werkzeug.routing import BuildError -from werkzeug.routing import Map -from werkzeug.routing import RequestRedirect -from werkzeug.routing import RoutingException -from werkzeug.routing import Rule -from werkzeug.wrappers import BaseResponse - -from . import cli -from . import json -from ._compat import integer_types -from ._compat import reraise -from ._compat import string_types -from ._compat import text_type -from .config import Config -from .config import ConfigAttribute -from .ctx import _AppCtxGlobals -from .ctx import AppContext -from .ctx import RequestContext -from .globals import _request_ctx_stack -from .globals import g -from .globals import request -from .globals import session -from .helpers import _endpoint_from_view_func -from .helpers import _PackageBoundObject -from .helpers import find_package -from .helpers import get_debug_flag -from .helpers import get_env -from .helpers import get_flashed_messages -from .helpers import get_load_dotenv -from .helpers import locked_cached_property -from .helpers import url_for -from .json import jsonify -from .logging import create_logger -from .sessions import SecureCookieSessionInterface -from .signals import appcontext_tearing_down -from .signals import got_request_exception -from .signals import request_finished -from .signals import request_started -from .signals import request_tearing_down -from .templating import _default_template_ctx_processor -from .templating import DispatchingJinjaLoader -from .templating import Environment -from .wrappers import Request -from .wrappers import Response - -# a singleton sentinel value for parameter defaults -_sentinel = object() - - -def _make_timedelta(value): - if not isinstance(value, timedelta): - return timedelta(seconds=value) - return value - - -def setupmethod(f): - """Wraps a method so that it performs a check in debug mode if the - first request was already handled. - """ - - def wrapper_func(self, *args, **kwargs): - if self.debug and self._got_first_request: - raise AssertionError( - "A setup function was called after the " - "first request was handled. This usually indicates a bug " - "in the application where a module was not imported " - "and decorators or other functionality was called too late.\n" - "To fix this make sure to import all your view modules, " - "database models and everything related at a central place " - "before the application starts serving requests." - ) - return f(self, *args, **kwargs) - - return update_wrapper(wrapper_func, f) - - -class Flask(_PackageBoundObject): - """The flask object implements a WSGI application and acts as the central - object. It is passed the name of the module or package of the - application. Once it is created it will act as a central registry for - the view functions, the URL rules, template configuration and much more. - - The name of the package is used to resolve resources from inside the - package or the folder the module is contained in depending on if the - package parameter resolves to an actual python package (a folder with - an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). - - For more information about resource loading, see :func:`open_resource`. - - Usually you create a :class:`Flask` instance in your main module or - in the :file:`__init__.py` file of your package like this:: - - from flask import Flask - app = Flask(__name__) - - .. admonition:: About the First Parameter - - The idea of the first parameter is to give Flask an idea of what - belongs to your application. This name is used to find resources - on the filesystem, can be used by extensions to improve debugging - information and a lot more. - - So it's important what you provide there. If you are using a single - module, `__name__` is always the correct value. If you however are - using a package, it's usually recommended to hardcode the name of - your package there. - - For example if your application is defined in :file:`yourapplication/app.py` - you should create it with one of the two versions below:: - - app = Flask('yourapplication') - app = Flask(__name__.split('.')[0]) - - Why is that? The application will work even with `__name__`, thanks - to how resources are looked up. However it will make debugging more - painful. Certain extensions can make assumptions based on the - import name of your application. For example the Flask-SQLAlchemy - extension will look for the code in your application that triggered - an SQL query in debug mode. If the import name is not properly set - up, that debugging information is lost. (For example it would only - pick up SQL queries in `yourapplication.app` and not - `yourapplication.views.frontend`) - - .. versionadded:: 0.7 - The `static_url_path`, `static_folder`, and `template_folder` - parameters were added. - - .. versionadded:: 0.8 - The `instance_path` and `instance_relative_config` parameters were - added. - - .. versionadded:: 0.11 - The `root_path` parameter was added. - - .. versionadded:: 1.0 - The ``host_matching`` and ``static_host`` parameters were added. - - .. versionadded:: 1.0 - The ``subdomain_matching`` parameter was added. Subdomain - matching needs to be enabled manually now. Setting - :data:`SERVER_NAME` does not implicitly enable it. - - :param import_name: the name of the application package - :param static_url_path: can be used to specify a different path for the - static files on the web. Defaults to the name - of the `static_folder` folder. - :param static_folder: The folder with static files that is served at - ``static_url_path``. Relative to the application ``root_path`` - or an absolute path. Defaults to ``'static'``. - :param static_host: the host to use when adding the static route. - Defaults to None. Required when using ``host_matching=True`` - with a ``static_folder`` configured. - :param host_matching: set ``url_map.host_matching`` attribute. - Defaults to False. - :param subdomain_matching: consider the subdomain relative to - :data:`SERVER_NAME` when matching routes. Defaults to False. - :param template_folder: the folder that contains the templates that should - be used by the application. Defaults to - ``'templates'`` folder in the root path of the - application. - :param instance_path: An alternative instance path for the application. - By default the folder ``'instance'`` next to the - package or module is assumed to be the instance - path. - :param instance_relative_config: if set to ``True`` relative filenames - for loading the config are assumed to - be relative to the instance path instead - of the application root. - :param root_path: Flask by default will automatically calculate the path - to the root of the application. In certain situations - this cannot be achieved (for instance if the package - is a Python 3 namespace package) and needs to be - manually defined. - """ - - #: The class that is used for request objects. See :class:`~flask.Request` - #: for more information. - request_class = Request - - #: The class that is used for response objects. See - #: :class:`~flask.Response` for more information. - response_class = Response - - #: The class that is used for the Jinja environment. - #: - #: .. versionadded:: 0.11 - jinja_environment = Environment - - #: The class that is used for the :data:`~flask.g` instance. - #: - #: Example use cases for a custom class: - #: - #: 1. Store arbitrary attributes on flask.g. - #: 2. Add a property for lazy per-request database connectors. - #: 3. Return None instead of AttributeError on unexpected attributes. - #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. - #: - #: In Flask 0.9 this property was called `request_globals_class` but it - #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the - #: flask.g object is now application context scoped. - #: - #: .. versionadded:: 0.10 - app_ctx_globals_class = _AppCtxGlobals - - #: The class that is used for the ``config`` attribute of this app. - #: Defaults to :class:`~flask.Config`. - #: - #: Example use cases for a custom class: - #: - #: 1. Default values for certain config options. - #: 2. Access to config values through attributes in addition to keys. - #: - #: .. versionadded:: 0.11 - config_class = Config - - #: The testing flag. Set this to ``True`` to enable the test mode of - #: Flask extensions (and in the future probably also Flask itself). - #: For example this might activate test helpers that have an - #: additional runtime cost which should not be enabled by default. - #: - #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the - #: default it's implicitly enabled. - #: - #: This attribute can also be configured from the config with the - #: ``TESTING`` configuration key. Defaults to ``False``. - testing = ConfigAttribute("TESTING") - - #: If a secret key is set, cryptographic components can use this to - #: sign cookies and other things. Set this to a complex random value - #: when you want to use the secure cookie for instance. - #: - #: This attribute can also be configured from the config with the - #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. - secret_key = ConfigAttribute("SECRET_KEY") - - #: The secure cookie uses this for the name of the session cookie. - #: - #: This attribute can also be configured from the config with the - #: ``SESSION_COOKIE_NAME`` configuration key. Defaults to ``'session'`` - session_cookie_name = ConfigAttribute("SESSION_COOKIE_NAME") - - #: A :class:`~datetime.timedelta` which is used to set the expiration - #: date of a permanent session. The default is 31 days which makes a - #: permanent session survive for roughly one month. - #: - #: This attribute can also be configured from the config with the - #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to - #: ``timedelta(days=31)`` - permanent_session_lifetime = ConfigAttribute( - "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta - ) - - #: A :class:`~datetime.timedelta` which is used as default cache_timeout - #: for the :func:`send_file` functions. The default is 12 hours. - #: - #: This attribute can also be configured from the config with the - #: ``SEND_FILE_MAX_AGE_DEFAULT`` configuration key. This configuration - #: variable can also be set with an integer value used as seconds. - #: Defaults to ``timedelta(hours=12)`` - send_file_max_age_default = ConfigAttribute( - "SEND_FILE_MAX_AGE_DEFAULT", get_converter=_make_timedelta - ) - - #: Enable this if you want to use the X-Sendfile feature. Keep in - #: mind that the server has to support this. This only affects files - #: sent with the :func:`send_file` method. - #: - #: .. versionadded:: 0.2 - #: - #: This attribute can also be configured from the config with the - #: ``USE_X_SENDFILE`` configuration key. Defaults to ``False``. - use_x_sendfile = ConfigAttribute("USE_X_SENDFILE") - - #: The JSON encoder class to use. Defaults to :class:`~flask.json.JSONEncoder`. - #: - #: .. versionadded:: 0.10 - json_encoder = json.JSONEncoder - - #: The JSON decoder class to use. Defaults to :class:`~flask.json.JSONDecoder`. - #: - #: .. versionadded:: 0.10 - json_decoder = json.JSONDecoder - - #: Options that are passed to the Jinja environment in - #: :meth:`create_jinja_environment`. Changing these options after - #: the environment is created (accessing :attr:`jinja_env`) will - #: have no effect. - #: - #: .. versionchanged:: 1.1.0 - #: This is a ``dict`` instead of an ``ImmutableDict`` to allow - #: easier configuration. - #: - jinja_options = {"extensions": ["jinja2.ext.autoescape", "jinja2.ext.with_"]} - - #: Default configuration parameters. - default_config = ImmutableDict( - { - "ENV": None, - "DEBUG": None, - "TESTING": False, - "PROPAGATE_EXCEPTIONS": None, - "PRESERVE_CONTEXT_ON_EXCEPTION": None, - "SECRET_KEY": None, - "PERMANENT_SESSION_LIFETIME": timedelta(days=31), - "USE_X_SENDFILE": False, - "SERVER_NAME": None, - "APPLICATION_ROOT": "/", - "SESSION_COOKIE_NAME": "session", - "SESSION_COOKIE_DOMAIN": None, - "SESSION_COOKIE_PATH": None, - "SESSION_COOKIE_HTTPONLY": True, - "SESSION_COOKIE_SECURE": False, - "SESSION_COOKIE_SAMESITE": None, - "SESSION_REFRESH_EACH_REQUEST": True, - "MAX_CONTENT_LENGTH": None, - "SEND_FILE_MAX_AGE_DEFAULT": timedelta(hours=12), - "TRAP_BAD_REQUEST_ERRORS": None, - "TRAP_HTTP_EXCEPTIONS": False, - "EXPLAIN_TEMPLATE_LOADING": False, - "PREFERRED_URL_SCHEME": "http", - "JSON_AS_ASCII": True, - "JSON_SORT_KEYS": True, - "JSONIFY_PRETTYPRINT_REGULAR": False, - "JSONIFY_MIMETYPE": "application/json", - "TEMPLATES_AUTO_RELOAD": None, - "MAX_COOKIE_SIZE": 4093, - } - ) - - #: The rule object to use for URL rules created. This is used by - #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. - #: - #: .. versionadded:: 0.7 - url_rule_class = Rule - - #: The map object to use for storing the URL rules and routing - #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. - #: - #: .. versionadded:: 1.1.0 - url_map_class = Map - - #: the test client that is used with when `test_client` is used. - #: - #: .. versionadded:: 0.7 - test_client_class = None - - #: The :class:`~click.testing.CliRunner` subclass, by default - #: :class:`~flask.testing.FlaskCliRunner` that is used by - #: :meth:`test_cli_runner`. Its ``__init__`` method should take a - #: Flask app object as the first argument. - #: - #: .. versionadded:: 1.0 - test_cli_runner_class = None - - #: the session interface to use. By default an instance of - #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. - #: - #: .. versionadded:: 0.8 - session_interface = SecureCookieSessionInterface() - - # TODO remove the next three attrs when Sphinx :inherited-members: works - # https://github.com/sphinx-doc/sphinx/issues/741 - - #: The name of the package or module that this app belongs to. Do not - #: change this once it is set by the constructor. - import_name = None - - #: Location of the template files to be added to the template lookup. - #: ``None`` if templates should not be added. - template_folder = None - - #: Absolute path to the package on the filesystem. Used to look up - #: resources contained in the package. - root_path = None - - def __init__( - self, - import_name, - static_url_path=None, - static_folder="static", - static_host=None, - host_matching=False, - subdomain_matching=False, - template_folder="templates", - instance_path=None, - instance_relative_config=False, - root_path=None, - ): - _PackageBoundObject.__init__( - self, import_name, template_folder=template_folder, root_path=root_path - ) - - self.static_url_path = static_url_path - self.static_folder = static_folder - - if instance_path is None: - instance_path = self.auto_find_instance_path() - elif not os.path.isabs(instance_path): - raise ValueError( - "If an instance path is provided it must be absolute." - " A relative path was given instead." - ) - - #: Holds the path to the instance folder. - #: - #: .. versionadded:: 0.8 - self.instance_path = instance_path - - #: The configuration dictionary as :class:`Config`. This behaves - #: exactly like a regular dictionary but supports additional methods - #: to load a config from files. - self.config = self.make_config(instance_relative_config) - - #: A dictionary of all view functions registered. The keys will - #: be function names which are also used to generate URLs and - #: the values are the function objects themselves. - #: To register a view function, use the :meth:`route` decorator. - self.view_functions = {} - - #: A dictionary of all registered error handlers. The key is ``None`` - #: for error handlers active on the application, otherwise the key is - #: the name of the blueprint. Each key points to another dictionary - #: where the key is the status code of the http exception. The - #: special key ``None`` points to a list of tuples where the first item - #: is the class for the instance check and the second the error handler - #: function. - #: - #: To register an error handler, use the :meth:`errorhandler` - #: decorator. - self.error_handler_spec = {} - - #: A list of functions that are called when :meth:`url_for` raises a - #: :exc:`~werkzeug.routing.BuildError`. Each function registered here - #: is called with `error`, `endpoint` and `values`. If a function - #: returns ``None`` or raises a :exc:`BuildError` the next function is - #: tried. - #: - #: .. versionadded:: 0.9 - self.url_build_error_handlers = [] - - #: A dictionary with lists of functions that will be called at the - #: beginning of each request. The key of the dictionary is the name of - #: the blueprint this function is active for, or ``None`` for all - #: requests. To register a function, use the :meth:`before_request` - #: decorator. - self.before_request_funcs = {} - - #: A list of functions that will be called at the beginning of the - #: first request to this instance. To register a function, use the - #: :meth:`before_first_request` decorator. - #: - #: .. versionadded:: 0.8 - self.before_first_request_funcs = [] - - #: A dictionary with lists of functions that should be called after - #: each request. The key of the dictionary is the name of the blueprint - #: this function is active for, ``None`` for all requests. This can for - #: example be used to close database connections. To register a function - #: here, use the :meth:`after_request` decorator. - self.after_request_funcs = {} - - #: A dictionary with lists of functions that are called after - #: each request, even if an exception has occurred. The key of the - #: dictionary is the name of the blueprint this function is active for, - #: ``None`` for all requests. These functions are not allowed to modify - #: the request, and their return values are ignored. If an exception - #: occurred while processing the request, it gets passed to each - #: teardown_request function. To register a function here, use the - #: :meth:`teardown_request` decorator. - #: - #: .. versionadded:: 0.7 - self.teardown_request_funcs = {} - - #: A list of functions that are called when the application context - #: is destroyed. Since the application context is also torn down - #: if the request ends this is the place to store code that disconnects - #: from databases. - #: - #: .. versionadded:: 0.9 - self.teardown_appcontext_funcs = [] - - #: A dictionary with lists of functions that are called before the - #: :attr:`before_request_funcs` functions. The key of the dictionary is - #: the name of the blueprint this function is active for, or ``None`` - #: for all requests. To register a function, use - #: :meth:`url_value_preprocessor`. - #: - #: .. versionadded:: 0.7 - self.url_value_preprocessors = {} - - #: A dictionary with lists of functions that can be used as URL value - #: preprocessors. The key ``None`` here is used for application wide - #: callbacks, otherwise the key is the name of the blueprint. - #: Each of these functions has the chance to modify the dictionary - #: of URL values before they are used as the keyword arguments of the - #: view function. For each function registered this one should also - #: provide a :meth:`url_defaults` function that adds the parameters - #: automatically again that were removed that way. - #: - #: .. versionadded:: 0.7 - self.url_default_functions = {} - - #: A dictionary with list of functions that are called without argument - #: to populate the template context. The key of the dictionary is the - #: name of the blueprint this function is active for, ``None`` for all - #: requests. Each returns a dictionary that the template context is - #: updated with. To register a function here, use the - #: :meth:`context_processor` decorator. - self.template_context_processors = {None: [_default_template_ctx_processor]} - - #: A list of shell context processor functions that should be run - #: when a shell context is created. - #: - #: .. versionadded:: 0.11 - self.shell_context_processors = [] - - #: all the attached blueprints in a dictionary by name. Blueprints - #: can be attached multiple times so this dictionary does not tell - #: you how often they got attached. - #: - #: .. versionadded:: 0.7 - self.blueprints = {} - self._blueprint_order = [] - - #: a place where extensions can store application specific state. For - #: example this is where an extension could store database engines and - #: similar things. For backwards compatibility extensions should register - #: themselves like this:: - #: - #: if not hasattr(app, 'extensions'): - #: app.extensions = {} - #: app.extensions['extensionname'] = SomeObject() - #: - #: The key must match the name of the extension module. For example in - #: case of a "Flask-Foo" extension in `flask_foo`, the key would be - #: ``'foo'``. - #: - #: .. versionadded:: 0.7 - self.extensions = {} - - #: The :class:`~werkzeug.routing.Map` for this instance. You can use - #: this to change the routing converters after the class was created - #: but before any routes are connected. Example:: - #: - #: from werkzeug.routing import BaseConverter - #: - #: class ListConverter(BaseConverter): - #: def to_python(self, value): - #: return value.split(',') - #: def to_url(self, values): - #: return ','.join(super(ListConverter, self).to_url(value) - #: for value in values) - #: - #: app = Flask(__name__) - #: app.url_map.converters['list'] = ListConverter - self.url_map = self.url_map_class() - - self.url_map.host_matching = host_matching - self.subdomain_matching = subdomain_matching - - # tracks internally if the application already handled at least one - # request. - self._got_first_request = False - self._before_request_lock = Lock() - - # Add a static route using the provided static_url_path, static_host, - # and static_folder if there is a configured static_folder. - # Note we do this without checking if static_folder exists. - # For one, it might be created while the server is running (e.g. during - # development). Also, Google App Engine stores static files somewhere - if self.has_static_folder: - assert ( - bool(static_host) == host_matching - ), "Invalid static_host/host_matching combination" - self.add_url_rule( - self.static_url_path + "/", - endpoint="static", - host=static_host, - view_func=self.send_static_file, - ) - - # Set the name of the Click group in case someone wants to add - # the app's commands to another CLI tool. - self.cli.name = self.name - - @locked_cached_property - def name(self): - """The name of the application. This is usually the import name - with the difference that it's guessed from the run file if the - import name is main. This name is used as a display name when - Flask needs the name of the application. It can be set and overridden - to change the value. - - .. versionadded:: 0.8 - """ - if self.import_name == "__main__": - fn = getattr(sys.modules["__main__"], "__file__", None) - if fn is None: - return "__main__" - return os.path.splitext(os.path.basename(fn))[0] - return self.import_name - - @property - def propagate_exceptions(self): - """Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration - value in case it's set, otherwise a sensible default is returned. - - .. versionadded:: 0.7 - """ - rv = self.config["PROPAGATE_EXCEPTIONS"] - if rv is not None: - return rv - return self.testing or self.debug - - @property - def preserve_context_on_exception(self): - """Returns the value of the ``PRESERVE_CONTEXT_ON_EXCEPTION`` - configuration value in case it's set, otherwise a sensible default - is returned. - - .. versionadded:: 0.7 - """ - rv = self.config["PRESERVE_CONTEXT_ON_EXCEPTION"] - if rv is not None: - return rv - return self.debug - - @locked_cached_property - def logger(self): - """A standard Python :class:`~logging.Logger` for the app, with - the same name as :attr:`name`. - - In debug mode, the logger's :attr:`~logging.Logger.level` will - be set to :data:`~logging.DEBUG`. - - If there are no handlers configured, a default handler will be - added. See :doc:`/logging` for more information. - - .. versionchanged:: 1.1.0 - The logger takes the same name as :attr:`name` rather than - hard-coding ``"flask.app"``. - - .. versionchanged:: 1.0.0 - Behavior was simplified. The logger is always named - ``"flask.app"``. The level is only set during configuration, - it doesn't check ``app.debug`` each time. Only one format is - used, not different ones depending on ``app.debug``. No - handlers are removed, and a handler is only added if no - handlers are already configured. - - .. versionadded:: 0.3 - """ - return create_logger(self) - - @locked_cached_property - def jinja_env(self): - """The Jinja environment used to load templates. - - The environment is created the first time this property is - accessed. Changing :attr:`jinja_options` after that will have no - effect. - """ - return self.create_jinja_environment() - - @property - def got_first_request(self): - """This attribute is set to ``True`` if the application started - handling the first request. - - .. versionadded:: 0.8 - """ - return self._got_first_request - - def make_config(self, instance_relative=False): - """Used to create the config attribute by the Flask constructor. - The `instance_relative` parameter is passed in from the constructor - of Flask (there named `instance_relative_config`) and indicates if - the config should be relative to the instance path or the root path - of the application. - - .. versionadded:: 0.8 - """ - root_path = self.root_path - if instance_relative: - root_path = self.instance_path - defaults = dict(self.default_config) - defaults["ENV"] = get_env() - defaults["DEBUG"] = get_debug_flag() - return self.config_class(root_path, defaults) - - def auto_find_instance_path(self): - """Tries to locate the instance path if it was not provided to the - constructor of the application class. It will basically calculate - the path to a folder named ``instance`` next to your main file or - the package. - - .. versionadded:: 0.8 - """ - prefix, package_path = find_package(self.import_name) - if prefix is None: - return os.path.join(package_path, "instance") - return os.path.join(prefix, "var", self.name + "-instance") - - def open_instance_resource(self, resource, mode="rb"): - """Opens a resource from the application's instance folder - (:attr:`instance_path`). Otherwise works like - :meth:`open_resource`. Instance resources can also be opened for - writing. - - :param resource: the name of the resource. To access resources within - subfolders use forward slashes as separator. - :param mode: resource file opening mode, default is 'rb'. - """ - return open(os.path.join(self.instance_path, resource), mode) - - @property - def templates_auto_reload(self): - """Reload templates when they are changed. Used by - :meth:`create_jinja_environment`. - - This attribute can be configured with :data:`TEMPLATES_AUTO_RELOAD`. If - not set, it will be enabled in debug mode. - - .. versionadded:: 1.0 - This property was added but the underlying config and behavior - already existed. - """ - rv = self.config["TEMPLATES_AUTO_RELOAD"] - return rv if rv is not None else self.debug - - @templates_auto_reload.setter - def templates_auto_reload(self, value): - self.config["TEMPLATES_AUTO_RELOAD"] = value - - def create_jinja_environment(self): - """Create the Jinja environment based on :attr:`jinja_options` - and the various Jinja-related methods of the app. Changing - :attr:`jinja_options` after this will have no effect. Also adds - Flask-related globals and filters to the environment. - - .. versionchanged:: 0.11 - ``Environment.auto_reload`` set in accordance with - ``TEMPLATES_AUTO_RELOAD`` configuration option. - - .. versionadded:: 0.5 - """ - options = dict(self.jinja_options) - - if "autoescape" not in options: - options["autoescape"] = self.select_jinja_autoescape - - if "auto_reload" not in options: - options["auto_reload"] = self.templates_auto_reload - - rv = self.jinja_environment(self, **options) - rv.globals.update( - url_for=url_for, - get_flashed_messages=get_flashed_messages, - config=self.config, - # request, session and g are normally added with the - # context processor for efficiency reasons but for imported - # templates we also want the proxies in there. - request=request, - session=session, - g=g, - ) - rv.filters["tojson"] = json.tojson_filter - return rv - - def create_global_jinja_loader(self): - """Creates the loader for the Jinja2 environment. Can be used to - override just the loader and keeping the rest unchanged. It's - discouraged to override this function. Instead one should override - the :meth:`jinja_loader` function instead. - - The global loader dispatches between the loaders of the application - and the individual blueprints. - - .. versionadded:: 0.7 - """ - return DispatchingJinjaLoader(self) - - def select_jinja_autoescape(self, filename): - """Returns ``True`` if autoescaping should be active for the given - template name. If no template name is given, returns `True`. - - .. versionadded:: 0.5 - """ - if filename is None: - return True - return filename.endswith((".html", ".htm", ".xml", ".xhtml")) - - def update_template_context(self, context): - """Update the template context with some commonly used variables. - This injects request, session, config and g into the template - context as well as everything template context processors want - to inject. Note that the as of Flask 0.6, the original values - in the context will not be overridden if a context processor - decides to return a value with the same key. - - :param context: the context as a dictionary that is updated in place - to add extra variables. - """ - funcs = self.template_context_processors[None] - reqctx = _request_ctx_stack.top - if reqctx is not None: - bp = reqctx.request.blueprint - if bp is not None and bp in self.template_context_processors: - funcs = chain(funcs, self.template_context_processors[bp]) - orig_ctx = context.copy() - for func in funcs: - context.update(func()) - # make sure the original values win. This makes it possible to - # easier add new variables in context processors without breaking - # existing views. - context.update(orig_ctx) - - def make_shell_context(self): - """Returns the shell context for an interactive shell for this - application. This runs all the registered shell context - processors. - - .. versionadded:: 0.11 - """ - rv = {"app": self, "g": g} - for processor in self.shell_context_processors: - rv.update(processor()) - return rv - - #: What environment the app is running in. Flask and extensions may - #: enable behaviors based on the environment, such as enabling debug - #: mode. This maps to the :data:`ENV` config key. This is set by the - #: :envvar:`FLASK_ENV` environment variable and may not behave as - #: expected if set in code. - #: - #: **Do not enable development when deploying in production.** - #: - #: Default: ``'production'`` - env = ConfigAttribute("ENV") - - @property - def debug(self): - """Whether debug mode is enabled. When using ``flask run`` to start - the development server, an interactive debugger will be shown for - unhandled exceptions, and the server will be reloaded when code - changes. This maps to the :data:`DEBUG` config key. This is - enabled when :attr:`env` is ``'development'`` and is overridden - by the ``FLASK_DEBUG`` environment variable. It may not behave as - expected if set in code. - - **Do not enable debug mode when deploying in production.** - - Default: ``True`` if :attr:`env` is ``'development'``, or - ``False`` otherwise. - """ - return self.config["DEBUG"] - - @debug.setter - def debug(self, value): - self.config["DEBUG"] = value - self.jinja_env.auto_reload = self.templates_auto_reload - - def run(self, host=None, port=None, debug=None, load_dotenv=True, **options): - """Runs the application on a local development server. - - Do not use ``run()`` in a production setting. It is not intended to - meet security and performance requirements for a production server. - Instead, see :ref:`deployment` for WSGI server recommendations. - - If the :attr:`debug` flag is set the server will automatically reload - for code changes and show a debugger in case an exception happened. - - If you want to run the application in debug mode, but disable the - code execution on the interactive debugger, you can pass - ``use_evalex=False`` as parameter. This will keep the debugger's - traceback screen active, but disable code execution. - - It is not recommended to use this function for development with - automatic reloading as this is badly supported. Instead you should - be using the :command:`flask` command line script's ``run`` support. - - .. admonition:: Keep in Mind - - Flask will suppress any server error with a generic error page - unless it is in debug mode. As such to enable just the - interactive debugger without the code reloading, you have to - invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. - Setting ``use_debugger`` to ``True`` without being in debug mode - won't catch any exceptions because there won't be any to - catch. - - :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to - have the server available externally as well. Defaults to - ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable - if present. - :param port: the port of the webserver. Defaults to ``5000`` or the - port defined in the ``SERVER_NAME`` config variable if present. - :param debug: if given, enable or disable debug mode. See - :attr:`debug`. - :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` - files to set environment variables. Will also change the working - directory to the directory containing the first file found. - :param options: the options to be forwarded to the underlying Werkzeug - server. See :func:`werkzeug.serving.run_simple` for more - information. - - .. versionchanged:: 1.0 - If installed, python-dotenv will be used to load environment - variables from :file:`.env` and :file:`.flaskenv` files. - - If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG` - environment variables will override :attr:`env` and - :attr:`debug`. - - Threaded mode is enabled by default. - - .. versionchanged:: 0.10 - The default port is now picked from the ``SERVER_NAME`` - variable. - """ - # Change this into a no-op if the server is invoked from the - # command line. Have a look at cli.py for more information. - if os.environ.get("FLASK_RUN_FROM_CLI") == "true": - from .debughelpers import explain_ignored_app_run - - explain_ignored_app_run() - return - - if get_load_dotenv(load_dotenv): - cli.load_dotenv() - - # if set, let env vars override previous values - if "FLASK_ENV" in os.environ: - self.env = get_env() - self.debug = get_debug_flag() - elif "FLASK_DEBUG" in os.environ: - self.debug = get_debug_flag() - - # debug passed to method overrides all other sources - if debug is not None: - self.debug = bool(debug) - - _host = "127.0.0.1" - _port = 5000 - server_name = self.config.get("SERVER_NAME") - sn_host, sn_port = None, None - - if server_name: - sn_host, _, sn_port = server_name.partition(":") - - host = host or sn_host or _host - # pick the first value that's not None (0 is allowed) - port = int(next((p for p in (port, sn_port) if p is not None), _port)) - - options.setdefault("use_reloader", self.debug) - options.setdefault("use_debugger", self.debug) - options.setdefault("threaded", True) - - cli.show_server_banner(self.env, self.debug, self.name, False) - - from werkzeug.serving import run_simple - - try: - run_simple(host, port, self, **options) - finally: - # reset the first request information if the development server - # reset normally. This makes it possible to restart the server - # without reloader and that stuff from an interactive shell. - self._got_first_request = False - - def test_client(self, use_cookies=True, **kwargs): - """Creates a test client for this application. For information - about unit testing head over to :ref:`testing`. - - Note that if you are testing for assertions or exceptions in your - application code, you must set ``app.testing = True`` in order for the - exceptions to propagate to the test client. Otherwise, the exception - will be handled by the application (not visible to the test client) and - the only indication of an AssertionError or other exception will be a - 500 status code response to the test client. See the :attr:`testing` - attribute. For example:: - - app.testing = True - client = app.test_client() - - The test client can be used in a ``with`` block to defer the closing down - of the context until the end of the ``with`` block. This is useful if - you want to access the context locals for testing:: - - with app.test_client() as c: - rv = c.get('/?vodka=42') - assert request.args['vodka'] == '42' - - Additionally, you may pass optional keyword arguments that will then - be passed to the application's :attr:`test_client_class` constructor. - For example:: - - from flask.testing import FlaskClient - - class CustomClient(FlaskClient): - def __init__(self, *args, **kwargs): - self._authentication = kwargs.pop("authentication") - super(CustomClient,self).__init__( *args, **kwargs) - - app.test_client_class = CustomClient - client = app.test_client(authentication='Basic ....') - - See :class:`~flask.testing.FlaskClient` for more information. - - .. versionchanged:: 0.4 - added support for ``with`` block usage for the client. - - .. versionadded:: 0.7 - The `use_cookies` parameter was added as well as the ability - to override the client to be used by setting the - :attr:`test_client_class` attribute. - - .. versionchanged:: 0.11 - Added `**kwargs` to support passing additional keyword arguments to - the constructor of :attr:`test_client_class`. - """ - cls = self.test_client_class - if cls is None: - from .testing import FlaskClient as cls - return cls(self, self.response_class, use_cookies=use_cookies, **kwargs) - - def test_cli_runner(self, **kwargs): - """Create a CLI runner for testing CLI commands. - See :ref:`testing-cli`. - - Returns an instance of :attr:`test_cli_runner_class`, by default - :class:`~flask.testing.FlaskCliRunner`. The Flask app object is - passed as the first argument. - - .. versionadded:: 1.0 - """ - cls = self.test_cli_runner_class - - if cls is None: - from .testing import FlaskCliRunner as cls - - return cls(self, **kwargs) - - def open_session(self, request): - """Creates or opens a new session. Default implementation stores all - session data in a signed cookie. This requires that the - :attr:`secret_key` is set. Instead of overriding this method - we recommend replacing the :class:`session_interface`. - - .. deprecated: 1.0 - Will be removed in 2.0. Use - ``session_interface.open_session`` instead. - - :param request: an instance of :attr:`request_class`. - """ - - warnings.warn( - DeprecationWarning( - '"open_session" is deprecated and will be removed in' - ' 2.0. Use "session_interface.open_session" instead.' - ) - ) - return self.session_interface.open_session(self, request) - - def save_session(self, session, response): - """Saves the session if it needs updates. For the default - implementation, check :meth:`open_session`. Instead of overriding this - method we recommend replacing the :class:`session_interface`. - - .. deprecated: 1.0 - Will be removed in 2.0. Use - ``session_interface.save_session`` instead. - - :param session: the session to be saved (a - :class:`~werkzeug.contrib.securecookie.SecureCookie` - object) - :param response: an instance of :attr:`response_class` - """ - - warnings.warn( - DeprecationWarning( - '"save_session" is deprecated and will be removed in' - ' 2.0. Use "session_interface.save_session" instead.' - ) - ) - return self.session_interface.save_session(self, session, response) - - def make_null_session(self): - """Creates a new instance of a missing session. Instead of overriding - this method we recommend replacing the :class:`session_interface`. - - .. deprecated: 1.0 - Will be removed in 2.0. Use - ``session_interface.make_null_session`` instead. - - .. versionadded:: 0.7 - """ - - warnings.warn( - DeprecationWarning( - '"make_null_session" is deprecated and will be removed' - ' in 2.0. Use "session_interface.make_null_session"' - " instead." - ) - ) - return self.session_interface.make_null_session(self) - - @setupmethod - def register_blueprint(self, blueprint, **options): - """Register a :class:`~flask.Blueprint` on the application. Keyword - arguments passed to this method will override the defaults set on the - blueprint. - - Calls the blueprint's :meth:`~flask.Blueprint.register` method after - recording the blueprint in the application's :attr:`blueprints`. - - :param blueprint: The blueprint to register. - :param url_prefix: Blueprint routes will be prefixed with this. - :param subdomain: Blueprint routes will match on this subdomain. - :param url_defaults: Blueprint routes will use these default values for - view arguments. - :param options: Additional keyword arguments are passed to - :class:`~flask.blueprints.BlueprintSetupState`. They can be - accessed in :meth:`~flask.Blueprint.record` callbacks. - - .. versionadded:: 0.7 - """ - first_registration = False - - if blueprint.name in self.blueprints: - assert self.blueprints[blueprint.name] is blueprint, ( - "A name collision occurred between blueprints %r and %r. Both" - ' share the same name "%s". Blueprints that are created on the' - " fly need unique names." - % (blueprint, self.blueprints[blueprint.name], blueprint.name) - ) - else: - self.blueprints[blueprint.name] = blueprint - self._blueprint_order.append(blueprint) - first_registration = True - - blueprint.register(self, options, first_registration) - - def iter_blueprints(self): - """Iterates over all blueprints by the order they were registered. - - .. versionadded:: 0.11 - """ - return iter(self._blueprint_order) - - @setupmethod - def add_url_rule( - self, - rule, - endpoint=None, - view_func=None, - provide_automatic_options=None, - **options - ): - """Connects a URL rule. Works exactly like the :meth:`route` - decorator. If a view_func is provided it will be registered with the - endpoint. - - Basically this example:: - - @app.route('/') - def index(): - pass - - Is equivalent to the following:: - - def index(): - pass - app.add_url_rule('/', 'index', index) - - If the view_func is not provided you will need to connect the endpoint - to a view function like so:: - - app.view_functions['index'] = index - - Internally :meth:`route` invokes :meth:`add_url_rule` so if you want - to customize the behavior via subclassing you only need to change - this method. - - For more information refer to :ref:`url-route-registrations`. - - .. versionchanged:: 0.2 - `view_func` parameter added. - - .. versionchanged:: 0.6 - ``OPTIONS`` is added automatically as method. - - :param rule: the URL rule as string - :param endpoint: the endpoint for the registered URL rule. Flask - itself assumes the name of the view function as - endpoint - :param view_func: the function to call when serving a request to the - provided endpoint - :param provide_automatic_options: controls whether the ``OPTIONS`` - method should be added automatically. This can also be controlled - by setting the ``view_func.provide_automatic_options = False`` - before adding the rule. - :param options: the options to be forwarded to the underlying - :class:`~werkzeug.routing.Rule` object. A change - to Werkzeug is handling of method options. methods - is a list of methods this rule should be limited - to (``GET``, ``POST`` etc.). By default a rule - just listens for ``GET`` (and implicitly ``HEAD``). - Starting with Flask 0.6, ``OPTIONS`` is implicitly - added and handled by the standard request handling. - """ - if endpoint is None: - endpoint = _endpoint_from_view_func(view_func) - options["endpoint"] = endpoint - methods = options.pop("methods", None) - - # if the methods are not given and the view_func object knows its - # methods we can use that instead. If neither exists, we go with - # a tuple of only ``GET`` as default. - if methods is None: - methods = getattr(view_func, "methods", None) or ("GET",) - if isinstance(methods, string_types): - raise TypeError( - "Allowed methods have to be iterables of strings, " - 'for example: @app.route(..., methods=["POST"])' - ) - methods = set(item.upper() for item in methods) - - # Methods that should always be added - required_methods = set(getattr(view_func, "required_methods", ())) - - # starting with Flask 0.8 the view_func object can disable and - # force-enable the automatic options handling. - if provide_automatic_options is None: - provide_automatic_options = getattr( - view_func, "provide_automatic_options", None - ) - - if provide_automatic_options is None: - if "OPTIONS" not in methods: - provide_automatic_options = True - required_methods.add("OPTIONS") - else: - provide_automatic_options = False - - # Add the required methods now. - methods |= required_methods - - rule = self.url_rule_class(rule, methods=methods, **options) - rule.provide_automatic_options = provide_automatic_options - - self.url_map.add(rule) - if view_func is not None: - old_func = self.view_functions.get(endpoint) - if old_func is not None and old_func != view_func: - raise AssertionError( - "View function mapping is overwriting an " - "existing endpoint function: %s" % endpoint - ) - self.view_functions[endpoint] = view_func - - def route(self, rule, **options): - """A decorator that is used to register a view function for a - given URL rule. This does the same thing as :meth:`add_url_rule` - but is intended for decorator usage:: - - @app.route('/') - def index(): - return 'Hello World' - - For more information refer to :ref:`url-route-registrations`. - - :param rule: the URL rule as string - :param endpoint: the endpoint for the registered URL rule. Flask - itself assumes the name of the view function as - endpoint - :param options: the options to be forwarded to the underlying - :class:`~werkzeug.routing.Rule` object. A change - to Werkzeug is handling of method options. methods - is a list of methods this rule should be limited - to (``GET``, ``POST`` etc.). By default a rule - just listens for ``GET`` (and implicitly ``HEAD``). - Starting with Flask 0.6, ``OPTIONS`` is implicitly - added and handled by the standard request handling. - """ - - def decorator(f): - endpoint = options.pop("endpoint", None) - self.add_url_rule(rule, endpoint, f, **options) - return f - - return decorator - - @setupmethod - def endpoint(self, endpoint): - """A decorator to register a function as an endpoint. - Example:: - - @app.endpoint('example.endpoint') - def example(): - return "example" - - :param endpoint: the name of the endpoint - """ - - def decorator(f): - self.view_functions[endpoint] = f - return f - - return decorator - - @staticmethod - def _get_exc_class_and_code(exc_class_or_code): - """Get the exception class being handled. For HTTP status codes - or ``HTTPException`` subclasses, return both the exception and - status code. - - :param exc_class_or_code: Any exception class, or an HTTP status - code as an integer. - """ - if isinstance(exc_class_or_code, integer_types): - exc_class = default_exceptions[exc_class_or_code] - else: - exc_class = exc_class_or_code - - assert issubclass(exc_class, Exception) - - if issubclass(exc_class, HTTPException): - return exc_class, exc_class.code - else: - return exc_class, None - - @setupmethod - def errorhandler(self, code_or_exception): - """Register a function to handle errors by code or exception class. - - A decorator that is used to register a function given an - error code. Example:: - - @app.errorhandler(404) - def page_not_found(error): - return 'This page does not exist', 404 - - You can also register handlers for arbitrary exceptions:: - - @app.errorhandler(DatabaseError) - def special_exception_handler(error): - return 'Database connection failed', 500 - - .. versionadded:: 0.7 - Use :meth:`register_error_handler` instead of modifying - :attr:`error_handler_spec` directly, for application wide error - handlers. - - .. versionadded:: 0.7 - One can now additionally also register custom exception types - that do not necessarily have to be a subclass of the - :class:`~werkzeug.exceptions.HTTPException` class. - - :param code_or_exception: the code as integer for the handler, or - an arbitrary exception - """ - - def decorator(f): - self._register_error_handler(None, code_or_exception, f) - return f - - return decorator - - @setupmethod - def register_error_handler(self, code_or_exception, f): - """Alternative error attach function to the :meth:`errorhandler` - decorator that is more straightforward to use for non decorator - usage. - - .. versionadded:: 0.7 - """ - self._register_error_handler(None, code_or_exception, f) - - @setupmethod - def _register_error_handler(self, key, code_or_exception, f): - """ - :type key: None|str - :type code_or_exception: int|T<=Exception - :type f: callable - """ - if isinstance(code_or_exception, HTTPException): # old broken behavior - raise ValueError( - "Tried to register a handler for an exception instance {0!r}." - " Handlers can only be registered for exception classes or" - " HTTP error codes.".format(code_or_exception) - ) - - try: - exc_class, code = self._get_exc_class_and_code(code_or_exception) - except KeyError: - raise KeyError( - "'{0}' is not a recognized HTTP error code. Use a subclass of" - " HTTPException with that code instead.".format(code_or_exception) - ) - - handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {}) - handlers[exc_class] = f - - @setupmethod - def template_filter(self, name=None): - """A decorator that is used to register custom template filter. - You can specify a name for the filter, otherwise the function - name will be used. Example:: - - @app.template_filter() - def reverse(s): - return s[::-1] - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_template_filter(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_filter(self, f, name=None): - """Register a custom template filter. Works exactly like the - :meth:`template_filter` decorator. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - self.jinja_env.filters[name or f.__name__] = f - - @setupmethod - def template_test(self, name=None): - """A decorator that is used to register custom template test. - You can specify a name for the test, otherwise the function - name will be used. Example:: - - @app.template_test() - def is_prime(n): - if n == 2: - return True - for i in range(2, int(math.ceil(math.sqrt(n))) + 1): - if n % i == 0: - return False - return True - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_template_test(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_test(self, f, name=None): - """Register a custom template test. Works exactly like the - :meth:`template_test` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - self.jinja_env.tests[name or f.__name__] = f - - @setupmethod - def template_global(self, name=None): - """A decorator that is used to register a custom template global function. - You can specify a name for the global function, otherwise the function - name will be used. Example:: - - @app.template_global() - def double(n): - return 2 * n - - .. versionadded:: 0.10 - - :param name: the optional name of the global function, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_template_global(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_global(self, f, name=None): - """Register a custom template global function. Works exactly like the - :meth:`template_global` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the global function, otherwise the - function name will be used. - """ - self.jinja_env.globals[name or f.__name__] = f - - @setupmethod - def before_request(self, f): - """Registers a function to run before each request. - - For example, this can be used to open a database connection, or to load - the logged in user from the session. - - The function will be called without any arguments. If it returns a - non-None value, the value is handled as if it was the return value from - the view, and further request handling is stopped. - """ - self.before_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def before_first_request(self, f): - """Registers a function to be run before the first request to this - instance of the application. - - The function will be called without any arguments and its return - value is ignored. - - .. versionadded:: 0.8 - """ - self.before_first_request_funcs.append(f) - return f - - @setupmethod - def after_request(self, f): - """Register a function to be run after each request. - - Your function must take one parameter, an instance of - :attr:`response_class` and return a new response object or the - same (see :meth:`process_response`). - - As of Flask 0.7 this function might not be executed at the end of the - request in case an unhandled exception occurred. - """ - self.after_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def teardown_request(self, f): - """Register a function to be run at the end of each request, - regardless of whether there was an exception or not. These functions - are executed when the request context is popped, even if not an - actual request was performed. - - Example:: - - ctx = app.test_request_context() - ctx.push() - ... - ctx.pop() - - When ``ctx.pop()`` is executed in the above example, the teardown - functions are called just before the request context moves from the - stack of active contexts. This becomes relevant if you are using - such constructs in tests. - - Generally teardown functions must take every necessary step to avoid - that they will fail. If they do execute code that might fail they - will have to surround the execution of these code by try/except - statements and log occurring errors. - - When a teardown function was called because of an exception it will - be passed an error object. - - The return values of teardown functions are ignored. - - .. admonition:: Debug Note - - In debug mode Flask will not tear down a request on an exception - immediately. Instead it will keep it alive so that the interactive - debugger can still access it. This behavior can be controlled - by the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. - """ - self.teardown_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def teardown_appcontext(self, f): - """Registers a function to be called when the application context - ends. These functions are typically also called when the request - context is popped. - - Example:: - - ctx = app.app_context() - ctx.push() - ... - ctx.pop() - - When ``ctx.pop()`` is executed in the above example, the teardown - functions are called just before the app context moves from the - stack of active contexts. This becomes relevant if you are using - such constructs in tests. - - Since a request context typically also manages an application - context it would also be called when you pop a request context. - - When a teardown function was called because of an unhandled exception - it will be passed an error object. If an :meth:`errorhandler` is - registered, it will handle the exception and the teardown will not - receive it. - - The return values of teardown functions are ignored. - - .. versionadded:: 0.9 - """ - self.teardown_appcontext_funcs.append(f) - return f - - @setupmethod - def context_processor(self, f): - """Registers a template context processor function.""" - self.template_context_processors[None].append(f) - return f - - @setupmethod - def shell_context_processor(self, f): - """Registers a shell context processor function. - - .. versionadded:: 0.11 - """ - self.shell_context_processors.append(f) - return f - - @setupmethod - def url_value_preprocessor(self, f): - """Register a URL value preprocessor function for all view - functions in the application. These functions will be called before the - :meth:`before_request` functions. - - The function can modify the values captured from the matched url before - they are passed to the view. For example, this can be used to pop a - common language code value and place it in ``g`` rather than pass it to - every view. - - The function is passed the endpoint name and values dict. The return - value is ignored. - """ - self.url_value_preprocessors.setdefault(None, []).append(f) - return f - - @setupmethod - def url_defaults(self, f): - """Callback function for URL defaults for all view functions of the - application. It's called with the endpoint and values and should - update the values passed in place. - """ - self.url_default_functions.setdefault(None, []).append(f) - return f - - def _find_error_handler(self, e): - """Return a registered error handler for an exception in this order: - blueprint handler for a specific code, app handler for a specific code, - blueprint handler for an exception class, app handler for an exception - class, or ``None`` if a suitable handler is not found. - """ - exc_class, code = self._get_exc_class_and_code(type(e)) - - for name, c in ( - (request.blueprint, code), - (None, code), - (request.blueprint, None), - (None, None), - ): - handler_map = self.error_handler_spec.setdefault(name, {}).get(c) - - if not handler_map: - continue - - for cls in exc_class.__mro__: - handler = handler_map.get(cls) - - if handler is not None: - return handler - - def handle_http_exception(self, e): - """Handles an HTTP exception. By default this will invoke the - registered error handlers and fall back to returning the - exception as response. - - .. versionchanged:: 1.0.3 - ``RoutingException``, used internally for actions such as - slash redirects during routing, is not passed to error - handlers. - - .. versionchanged:: 1.0 - Exceptions are looked up by code *and* by MRO, so - ``HTTPExcpetion`` subclasses can be handled with a catch-all - handler for the base ``HTTPException``. - - .. versionadded:: 0.3 - """ - # Proxy exceptions don't have error codes. We want to always return - # those unchanged as errors - if e.code is None: - return e - - # RoutingExceptions are used internally to trigger routing - # actions, such as slash redirects raising RequestRedirect. They - # are not raised or handled in user code. - if isinstance(e, RoutingException): - return e - - handler = self._find_error_handler(e) - if handler is None: - return e - return handler(e) - - def trap_http_exception(self, e): - """Checks if an HTTP exception should be trapped or not. By default - this will return ``False`` for all exceptions except for a bad request - key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It - also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. - - This is called for all HTTP exceptions raised by a view function. - If it returns ``True`` for any exception the error handler for this - exception is not called and it shows up as regular exception in the - traceback. This is helpful for debugging implicitly raised HTTP - exceptions. - - .. versionchanged:: 1.0 - Bad request errors are not trapped by default in debug mode. - - .. versionadded:: 0.8 - """ - if self.config["TRAP_HTTP_EXCEPTIONS"]: - return True - - trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] - - # if unset, trap key errors in debug mode - if ( - trap_bad_request is None - and self.debug - and isinstance(e, BadRequestKeyError) - ): - return True - - if trap_bad_request: - return isinstance(e, BadRequest) - - return False - - def handle_user_exception(self, e): - """This method is called whenever an exception occurs that - should be handled. A special case is :class:`~werkzeug - .exceptions.HTTPException` which is forwarded to the - :meth:`handle_http_exception` method. This function will either - return a response value or reraise the exception with the same - traceback. - - .. versionchanged:: 1.0 - Key errors raised from request data like ``form`` show the - bad key in debug mode rather than a generic bad request - message. - - .. versionadded:: 0.7 - """ - exc_type, exc_value, tb = sys.exc_info() - assert exc_value is e - # ensure not to trash sys.exc_info() at that point in case someone - # wants the traceback preserved in handle_http_exception. Of course - # we cannot prevent users from trashing it themselves in a custom - # trap_http_exception method so that's their fault then. - - if isinstance(e, BadRequestKeyError): - if self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]: - e.show_exception = True - - # Werkzeug < 0.15 doesn't add the KeyError to the 400 - # message, add it in manually. - # TODO: clean up once Werkzeug >= 0.15.5 is required - if e.args[0] not in e.get_description(): - e.description = "KeyError: '{}'".format(*e.args) - elif not hasattr(BadRequestKeyError, "show_exception"): - e.args = () - - if isinstance(e, HTTPException) and not self.trap_http_exception(e): - return self.handle_http_exception(e) - - handler = self._find_error_handler(e) - - if handler is None: - reraise(exc_type, exc_value, tb) - return handler(e) - - def handle_exception(self, e): - """Handle an exception that did not have an error handler - associated with it, or that was raised from an error handler. - This always causes a 500 ``InternalServerError``. - - Always sends the :data:`got_request_exception` signal. - - If :attr:`propagate_exceptions` is ``True``, such as in debug - mode, the error will be re-raised so that the debugger can - display it. Otherwise, the original exception is logged, and - an :exc:`~werkzeug.exceptions.InternalServerError` is returned. - - If an error handler is registered for ``InternalServerError`` or - ``500``, it will be used. For consistency, the handler will - always receive the ``InternalServerError``. The original - unhandled exception is available as ``e.original_exception``. - - .. note:: - Prior to Werkzeug 1.0.0, ``InternalServerError`` will not - always have an ``original_exception`` attribute. Use - ``getattr(e, "original_exception", None)`` to simulate the - behavior for compatibility. - - .. versionchanged:: 1.1.0 - Always passes the ``InternalServerError`` instance to the - handler, setting ``original_exception`` to the unhandled - error. - - .. versionchanged:: 1.1.0 - ``after_request`` functions and other finalization is done - even for the default 500 response when there is no handler. - - .. versionadded:: 0.3 - """ - exc_type, exc_value, tb = sys.exc_info() - got_request_exception.send(self, exception=e) - - if self.propagate_exceptions: - # if we want to repropagate the exception, we can attempt to - # raise it with the whole traceback in case we can do that - # (the function was actually called from the except part) - # otherwise, we just raise the error again - if exc_value is e: - reraise(exc_type, exc_value, tb) - else: - raise e - - self.log_exception((exc_type, exc_value, tb)) - server_error = InternalServerError() - # TODO: pass as param when Werkzeug>=1.0.0 is required - # TODO: also remove note about this from docstring and docs - server_error.original_exception = e - handler = self._find_error_handler(server_error) - - if handler is not None: - server_error = handler(server_error) - - return self.finalize_request(server_error, from_error_handler=True) - - def log_exception(self, exc_info): - """Logs an exception. This is called by :meth:`handle_exception` - if debugging is disabled and right before the handler is called. - The default implementation logs the exception as error on the - :attr:`logger`. - - .. versionadded:: 0.8 - """ - self.logger.error( - "Exception on %s [%s]" % (request.path, request.method), exc_info=exc_info - ) - - def raise_routing_exception(self, request): - """Exceptions that are recording during routing are reraised with - this method. During debug we are not reraising redirect requests - for non ``GET``, ``HEAD``, or ``OPTIONS`` requests and we're raising - a different error instead to help debug situations. - - :internal: - """ - if ( - not self.debug - or not isinstance(request.routing_exception, RequestRedirect) - or request.method in ("GET", "HEAD", "OPTIONS") - ): - raise request.routing_exception - - from .debughelpers import FormDataRoutingRedirect - - raise FormDataRoutingRedirect(request) - - def dispatch_request(self): - """Does the request dispatching. Matches the URL and returns the - return value of the view or error handler. This does not have to - be a response object. In order to convert the return value to a - proper response object, call :func:`make_response`. - - .. versionchanged:: 0.7 - This no longer does the exception handling, this code was - moved to the new :meth:`full_dispatch_request`. - """ - req = _request_ctx_stack.top.request - if req.routing_exception is not None: - self.raise_routing_exception(req) - rule = req.url_rule - # if we provide automatic options for this URL and the - # request came with the OPTIONS method, reply automatically - if ( - getattr(rule, "provide_automatic_options", False) - and req.method == "OPTIONS" - ): - return self.make_default_options_response() - # otherwise dispatch to the handler for that endpoint - return self.view_functions[rule.endpoint](**req.view_args) - - def full_dispatch_request(self): - """Dispatches the request and on top of that performs request - pre and postprocessing as well as HTTP exception catching and - error handling. - - .. versionadded:: 0.7 - """ - self.try_trigger_before_first_request_functions() - try: - request_started.send(self) - rv = self.preprocess_request() - if rv is None: - rv = self.dispatch_request() - except Exception as e: - rv = self.handle_user_exception(e) - return self.finalize_request(rv) - - def finalize_request(self, rv, from_error_handler=False): - """Given the return value from a view function this finalizes - the request by converting it into a response and invoking the - postprocessing functions. This is invoked for both normal - request dispatching as well as error handlers. - - Because this means that it might be called as a result of a - failure a special safe mode is available which can be enabled - with the `from_error_handler` flag. If enabled, failures in - response processing will be logged and otherwise ignored. - - :internal: - """ - response = self.make_response(rv) - try: - response = self.process_response(response) - request_finished.send(self, response=response) - except Exception: - if not from_error_handler: - raise - self.logger.exception( - "Request finalizing failed with an error while handling an error" - ) - return response - - def try_trigger_before_first_request_functions(self): - """Called before each request and will ensure that it triggers - the :attr:`before_first_request_funcs` and only exactly once per - application instance (which means process usually). - - :internal: - """ - if self._got_first_request: - return - with self._before_request_lock: - if self._got_first_request: - return - for func in self.before_first_request_funcs: - func() - self._got_first_request = True - - def make_default_options_response(self): - """This method is called to create the default ``OPTIONS`` response. - This can be changed through subclassing to change the default - behavior of ``OPTIONS`` responses. - - .. versionadded:: 0.7 - """ - adapter = _request_ctx_stack.top.url_adapter - if hasattr(adapter, "allowed_methods"): - methods = adapter.allowed_methods() - else: - # fallback for Werkzeug < 0.7 - methods = [] - try: - adapter.match(method="--") - except MethodNotAllowed as e: - methods = e.valid_methods - except HTTPException: - pass - rv = self.response_class() - rv.allow.update(methods) - return rv - - def should_ignore_error(self, error): - """This is called to figure out if an error should be ignored - or not as far as the teardown system is concerned. If this - function returns ``True`` then the teardown handlers will not be - passed the error. - - .. versionadded:: 0.10 - """ - return False - - def make_response(self, rv): - """Convert the return value from a view function to an instance of - :attr:`response_class`. - - :param rv: the return value from the view function. The view function - must return a response. Returning ``None``, or the view ending - without returning, is not allowed. The following types are allowed - for ``view_rv``: - - ``str`` (``unicode`` in Python 2) - A response object is created with the string encoded to UTF-8 - as the body. - - ``bytes`` (``str`` in Python 2) - A response object is created with the bytes as the body. - - ``dict`` - A dictionary that will be jsonify'd before being returned. - - ``tuple`` - Either ``(body, status, headers)``, ``(body, status)``, or - ``(body, headers)``, where ``body`` is any of the other types - allowed here, ``status`` is a string or an integer, and - ``headers`` is a dictionary or a list of ``(key, value)`` - tuples. If ``body`` is a :attr:`response_class` instance, - ``status`` overwrites the exiting value and ``headers`` are - extended. - - :attr:`response_class` - The object is returned unchanged. - - other :class:`~werkzeug.wrappers.Response` class - The object is coerced to :attr:`response_class`. - - :func:`callable` - The function is called as a WSGI application. The result is - used to create a response object. - - .. versionchanged:: 0.9 - Previously a tuple was interpreted as the arguments for the - response object. - """ - - status = headers = None - - # unpack tuple returns - if isinstance(rv, tuple): - len_rv = len(rv) - - # a 3-tuple is unpacked directly - if len_rv == 3: - rv, status, headers = rv - # decide if a 2-tuple has status or headers - elif len_rv == 2: - if isinstance(rv[1], (Headers, dict, tuple, list)): - rv, headers = rv - else: - rv, status = rv - # other sized tuples are not allowed - else: - raise TypeError( - "The view function did not return a valid response tuple." - " The tuple must have the form (body, status, headers)," - " (body, status), or (body, headers)." - ) - - # the body must not be None - if rv is None: - raise TypeError( - "The view function did not return a valid response. The" - " function either returned None or ended without a return" - " statement." - ) - - # make sure the body is an instance of the response class - if not isinstance(rv, self.response_class): - if isinstance(rv, (text_type, bytes, bytearray)): - # let the response class set the status and headers instead of - # waiting to do it manually, so that the class can handle any - # special logic - rv = self.response_class(rv, status=status, headers=headers) - status = headers = None - elif isinstance(rv, dict): - rv = jsonify(rv) - elif isinstance(rv, BaseResponse) or callable(rv): - # evaluate a WSGI callable, or coerce a different response - # class to the correct type - try: - rv = self.response_class.force_type(rv, request.environ) - except TypeError as e: - new_error = TypeError( - "{e}\nThe view function did not return a valid" - " response. The return type must be a string, dict, tuple," - " Response instance, or WSGI callable, but it was a" - " {rv.__class__.__name__}.".format(e=e, rv=rv) - ) - reraise(TypeError, new_error, sys.exc_info()[2]) - else: - raise TypeError( - "The view function did not return a valid" - " response. The return type must be a string, dict, tuple," - " Response instance, or WSGI callable, but it was a" - " {rv.__class__.__name__}.".format(rv=rv) - ) - - # prefer the status if it was provided - if status is not None: - if isinstance(status, (text_type, bytes, bytearray)): - rv.status = status - else: - rv.status_code = status - - # extend existing headers with provided headers - if headers: - rv.headers.extend(headers) - - return rv - - def create_url_adapter(self, request): - """Creates a URL adapter for the given request. The URL adapter - is created at a point where the request context is not yet set - up so the request is passed explicitly. - - .. versionadded:: 0.6 - - .. versionchanged:: 0.9 - This can now also be called without a request object when the - URL adapter is created for the application context. - - .. versionchanged:: 1.0 - :data:`SERVER_NAME` no longer implicitly enables subdomain - matching. Use :attr:`subdomain_matching` instead. - """ - if request is not None: - # If subdomain matching is disabled (the default), use the - # default subdomain in all cases. This should be the default - # in Werkzeug but it currently does not have that feature. - subdomain = ( - (self.url_map.default_subdomain or None) - if not self.subdomain_matching - else None - ) - return self.url_map.bind_to_environ( - request.environ, - server_name=self.config["SERVER_NAME"], - subdomain=subdomain, - ) - # We need at the very least the server name to be set for this - # to work. - if self.config["SERVER_NAME"] is not None: - return self.url_map.bind( - self.config["SERVER_NAME"], - script_name=self.config["APPLICATION_ROOT"], - url_scheme=self.config["PREFERRED_URL_SCHEME"], - ) - - def inject_url_defaults(self, endpoint, values): - """Injects the URL defaults for the given endpoint directly into - the values dictionary passed. This is used internally and - automatically called on URL building. - - .. versionadded:: 0.7 - """ - funcs = self.url_default_functions.get(None, ()) - if "." in endpoint: - bp = endpoint.rsplit(".", 1)[0] - funcs = chain(funcs, self.url_default_functions.get(bp, ())) - for func in funcs: - func(endpoint, values) - - def handle_url_build_error(self, error, endpoint, values): - """Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`. - """ - exc_type, exc_value, tb = sys.exc_info() - for handler in self.url_build_error_handlers: - try: - rv = handler(error, endpoint, values) - if rv is not None: - return rv - except BuildError as e: - # make error available outside except block (py3) - error = e - - # At this point we want to reraise the exception. If the error is - # still the same one we can reraise it with the original traceback, - # otherwise we raise it from here. - if error is exc_value: - reraise(exc_type, exc_value, tb) - raise error - - def preprocess_request(self): - """Called before the request is dispatched. Calls - :attr:`url_value_preprocessors` registered with the app and the - current blueprint (if any). Then calls :attr:`before_request_funcs` - registered with the app and the blueprint. - - If any :meth:`before_request` handler returns a non-None value, the - value is handled as if it was the return value from the view, and - further request handling is stopped. - """ - - bp = _request_ctx_stack.top.request.blueprint - - funcs = self.url_value_preprocessors.get(None, ()) - if bp is not None and bp in self.url_value_preprocessors: - funcs = chain(funcs, self.url_value_preprocessors[bp]) - for func in funcs: - func(request.endpoint, request.view_args) - - funcs = self.before_request_funcs.get(None, ()) - if bp is not None and bp in self.before_request_funcs: - funcs = chain(funcs, self.before_request_funcs[bp]) - for func in funcs: - rv = func() - if rv is not None: - return rv - - def process_response(self, response): - """Can be overridden in order to modify the response object - before it's sent to the WSGI server. By default this will - call all the :meth:`after_request` decorated functions. - - .. versionchanged:: 0.5 - As of Flask 0.5 the functions registered for after request - execution are called in reverse order of registration. - - :param response: a :attr:`response_class` object. - :return: a new response object or the same, has to be an - instance of :attr:`response_class`. - """ - ctx = _request_ctx_stack.top - bp = ctx.request.blueprint - funcs = ctx._after_request_functions - if bp is not None and bp in self.after_request_funcs: - funcs = chain(funcs, reversed(self.after_request_funcs[bp])) - if None in self.after_request_funcs: - funcs = chain(funcs, reversed(self.after_request_funcs[None])) - for handler in funcs: - response = handler(response) - if not self.session_interface.is_null_session(ctx.session): - self.session_interface.save_session(self, ctx.session, response) - return response - - def do_teardown_request(self, exc=_sentinel): - """Called after the request is dispatched and the response is - returned, right before the request context is popped. - - This calls all functions decorated with - :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` - if a blueprint handled the request. Finally, the - :data:`request_tearing_down` signal is sent. - - This is called by - :meth:`RequestContext.pop() `, - which may be delayed during testing to maintain access to - resources. - - :param exc: An unhandled exception raised while dispatching the - request. Detected from the current exception information if - not passed. Passed to each teardown function. - - .. versionchanged:: 0.9 - Added the ``exc`` argument. - """ - if exc is _sentinel: - exc = sys.exc_info()[1] - funcs = reversed(self.teardown_request_funcs.get(None, ())) - bp = _request_ctx_stack.top.request.blueprint - if bp is not None and bp in self.teardown_request_funcs: - funcs = chain(funcs, reversed(self.teardown_request_funcs[bp])) - for func in funcs: - func(exc) - request_tearing_down.send(self, exc=exc) - - def do_teardown_appcontext(self, exc=_sentinel): - """Called right before the application context is popped. - - When handling a request, the application context is popped - after the request context. See :meth:`do_teardown_request`. - - This calls all functions decorated with - :meth:`teardown_appcontext`. Then the - :data:`appcontext_tearing_down` signal is sent. - - This is called by - :meth:`AppContext.pop() `. - - .. versionadded:: 0.9 - """ - if exc is _sentinel: - exc = sys.exc_info()[1] - for func in reversed(self.teardown_appcontext_funcs): - func(exc) - appcontext_tearing_down.send(self, exc=exc) - - def app_context(self): - """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` - block to push the context, which will make :data:`current_app` - point at this application. - - An application context is automatically pushed by - :meth:`RequestContext.push() ` - when handling a request, and when running a CLI command. Use - this to manually create a context outside of these situations. - - :: - - with app.app_context(): - init_db() - - See :doc:`/appcontext`. - - .. versionadded:: 0.9 - """ - return AppContext(self) - - def request_context(self, environ): - """Create a :class:`~flask.ctx.RequestContext` representing a - WSGI environment. Use a ``with`` block to push the context, - which will make :data:`request` point at this request. - - See :doc:`/reqcontext`. - - Typically you should not call this from your own code. A request - context is automatically pushed by the :meth:`wsgi_app` when - handling a request. Use :meth:`test_request_context` to create - an environment and context instead of this method. - - :param environ: a WSGI environment - """ - return RequestContext(self, environ) - - def test_request_context(self, *args, **kwargs): - """Create a :class:`~flask.ctx.RequestContext` for a WSGI - environment created from the given values. This is mostly useful - during testing, where you may want to run a function that uses - request data without dispatching a full request. - - See :doc:`/reqcontext`. - - Use a ``with`` block to push the context, which will make - :data:`request` point at the request for the created - environment. :: - - with test_request_context(...): - generate_report() - - When using the shell, it may be easier to push and pop the - context manually to avoid indentation. :: - - ctx = app.test_request_context(...) - ctx.push() - ... - ctx.pop() - - Takes the same arguments as Werkzeug's - :class:`~werkzeug.test.EnvironBuilder`, with some defaults from - the application. See the linked Werkzeug docs for most of the - available arguments. Flask-specific behavior is listed here. - - :param path: URL path being requested. - :param base_url: Base URL where the app is being served, which - ``path`` is relative to. If not given, built from - :data:`PREFERRED_URL_SCHEME`, ``subdomain``, - :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. - :param subdomain: Subdomain name to append to - :data:`SERVER_NAME`. - :param url_scheme: Scheme to use instead of - :data:`PREFERRED_URL_SCHEME`. - :param data: The request body, either as a string or a dict of - form keys and values. - :param json: If given, this is serialized as JSON and passed as - ``data``. Also defaults ``content_type`` to - ``application/json``. - :param args: other positional arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - :param kwargs: other keyword arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - """ - from .testing import EnvironBuilder - - builder = EnvironBuilder(self, *args, **kwargs) - - try: - return self.request_context(builder.get_environ()) - finally: - builder.close() - - def wsgi_app(self, environ, start_response): - """The actual WSGI application. This is not implemented in - :meth:`__call__` so that middlewares can be applied without - losing a reference to the app object. Instead of doing this:: - - app = MyMiddleware(app) - - It's a better idea to do this instead:: - - app.wsgi_app = MyMiddleware(app.wsgi_app) - - Then you still have the original application object around and - can continue to call methods on it. - - .. versionchanged:: 0.7 - Teardown events for the request and app contexts are called - even if an unhandled error occurs. Other events may not be - called depending on when an error occurs during dispatch. - See :ref:`callbacks-and-errors`. - - :param environ: A WSGI environment. - :param start_response: A callable accepting a status code, - a list of headers, and an optional exception context to - start the response. - """ - ctx = self.request_context(environ) - error = None - try: - try: - ctx.push() - response = self.full_dispatch_request() - except Exception as e: - error = e - response = self.handle_exception(e) - except: # noqa: B001 - error = sys.exc_info()[1] - raise - return response(environ, start_response) - finally: - if self.should_ignore_error(error): - error = None - ctx.auto_pop(error) - - def __call__(self, environ, start_response): - """The WSGI server calls the Flask application object as the - WSGI application. This calls :meth:`wsgi_app` which can be - wrapped to applying middleware.""" - return self.wsgi_app(environ, start_response) - - def __repr__(self): - return "<%s %r>" % (self.__class__.__name__, self.name) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/blueprints.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/blueprints.py deleted file mode 100644 index 8978104..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/blueprints.py +++ /dev/null @@ -1,569 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.blueprints - ~~~~~~~~~~~~~~~~ - - Blueprints are the recommended way to implement larger or more - pluggable applications in Flask 0.7 and later. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -from functools import update_wrapper - -from .helpers import _endpoint_from_view_func -from .helpers import _PackageBoundObject - -# a singleton sentinel value for parameter defaults -_sentinel = object() - - -class BlueprintSetupState(object): - """Temporary holder object for registering a blueprint with the - application. An instance of this class is created by the - :meth:`~flask.Blueprint.make_setup_state` method and later passed - to all register callback functions. - """ - - def __init__(self, blueprint, app, options, first_registration): - #: a reference to the current application - self.app = app - - #: a reference to the blueprint that created this setup state. - self.blueprint = blueprint - - #: a dictionary with all options that were passed to the - #: :meth:`~flask.Flask.register_blueprint` method. - self.options = options - - #: as blueprints can be registered multiple times with the - #: application and not everything wants to be registered - #: multiple times on it, this attribute can be used to figure - #: out if the blueprint was registered in the past already. - self.first_registration = first_registration - - subdomain = self.options.get("subdomain") - if subdomain is None: - subdomain = self.blueprint.subdomain - - #: The subdomain that the blueprint should be active for, ``None`` - #: otherwise. - self.subdomain = subdomain - - url_prefix = self.options.get("url_prefix") - if url_prefix is None: - url_prefix = self.blueprint.url_prefix - #: The prefix that should be used for all URLs defined on the - #: blueprint. - self.url_prefix = url_prefix - - #: A dictionary with URL defaults that is added to each and every - #: URL that was defined with the blueprint. - self.url_defaults = dict(self.blueprint.url_values_defaults) - self.url_defaults.update(self.options.get("url_defaults", ())) - - def add_url_rule(self, rule, endpoint=None, view_func=None, **options): - """A helper method to register a rule (and optionally a view function) - to the application. The endpoint is automatically prefixed with the - blueprint's name. - """ - if self.url_prefix is not None: - if rule: - rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) - else: - rule = self.url_prefix - options.setdefault("subdomain", self.subdomain) - if endpoint is None: - endpoint = _endpoint_from_view_func(view_func) - defaults = self.url_defaults - if "defaults" in options: - defaults = dict(defaults, **options.pop("defaults")) - self.app.add_url_rule( - rule, - "%s.%s" % (self.blueprint.name, endpoint), - view_func, - defaults=defaults, - **options - ) - - -class Blueprint(_PackageBoundObject): - """Represents a blueprint, a collection of routes and other - app-related functions that can be registered on a real application - later. - - A blueprint is an object that allows defining application functions - without requiring an application object ahead of time. It uses the - same decorators as :class:`~flask.Flask`, but defers the need for an - application by recording them for later registration. - - Decorating a function with a blueprint creates a deferred function - that is called with :class:`~flask.blueprints.BlueprintSetupState` - when the blueprint is registered on an application. - - See :ref:`blueprints` for more information. - - .. versionchanged:: 1.1.0 - Blueprints have a ``cli`` group to register nested CLI commands. - The ``cli_group`` parameter controls the name of the group under - the ``flask`` command. - - .. versionadded:: 0.7 - - :param name: The name of the blueprint. Will be prepended to each - endpoint name. - :param import_name: The name of the blueprint package, usually - ``__name__``. This helps locate the ``root_path`` for the - blueprint. - :param static_folder: A folder with static files that should be - served by the blueprint's static route. The path is relative to - the blueprint's root path. Blueprint static files are disabled - by default. - :param static_url_path: The url to serve static files from. - Defaults to ``static_folder``. If the blueprint does not have - a ``url_prefix``, the app's static route will take precedence, - and the blueprint's static files won't be accessible. - :param template_folder: A folder with templates that should be added - to the app's template search path. The path is relative to the - blueprint's root path. Blueprint templates are disabled by - default. Blueprint templates have a lower precedence than those - in the app's templates folder. - :param url_prefix: A path to prepend to all of the blueprint's URLs, - to make them distinct from the rest of the app's routes. - :param subdomain: A subdomain that blueprint routes will match on by - default. - :param url_defaults: A dict of default values that blueprint routes - will receive by default. - :param root_path: By default, the blueprint will automatically this - based on ``import_name``. In certain situations this automatic - detection can fail, so the path can be specified manually - instead. - """ - - warn_on_modifications = False - _got_registered_once = False - - #: Blueprint local JSON decoder class to use. - #: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_encoder`. - json_encoder = None - #: Blueprint local JSON decoder class to use. - #: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_decoder`. - json_decoder = None - - # TODO remove the next three attrs when Sphinx :inherited-members: works - # https://github.com/sphinx-doc/sphinx/issues/741 - - #: The name of the package or module that this app belongs to. Do not - #: change this once it is set by the constructor. - import_name = None - - #: Location of the template files to be added to the template lookup. - #: ``None`` if templates should not be added. - template_folder = None - - #: Absolute path to the package on the filesystem. Used to look up - #: resources contained in the package. - root_path = None - - def __init__( - self, - name, - import_name, - static_folder=None, - static_url_path=None, - template_folder=None, - url_prefix=None, - subdomain=None, - url_defaults=None, - root_path=None, - cli_group=_sentinel, - ): - _PackageBoundObject.__init__( - self, import_name, template_folder, root_path=root_path - ) - self.name = name - self.url_prefix = url_prefix - self.subdomain = subdomain - self.static_folder = static_folder - self.static_url_path = static_url_path - self.deferred_functions = [] - if url_defaults is None: - url_defaults = {} - self.url_values_defaults = url_defaults - self.cli_group = cli_group - - def record(self, func): - """Registers a function that is called when the blueprint is - registered on the application. This function is called with the - state as argument as returned by the :meth:`make_setup_state` - method. - """ - if self._got_registered_once and self.warn_on_modifications: - from warnings import warn - - warn( - Warning( - "The blueprint was already registered once " - "but is getting modified now. These changes " - "will not show up." - ) - ) - self.deferred_functions.append(func) - - def record_once(self, func): - """Works like :meth:`record` but wraps the function in another - function that will ensure the function is only called once. If the - blueprint is registered a second time on the application, the - function passed is not called. - """ - - def wrapper(state): - if state.first_registration: - func(state) - - return self.record(update_wrapper(wrapper, func)) - - def make_setup_state(self, app, options, first_registration=False): - """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` - object that is later passed to the register callback functions. - Subclasses can override this to return a subclass of the setup state. - """ - return BlueprintSetupState(self, app, options, first_registration) - - def register(self, app, options, first_registration=False): - """Called by :meth:`Flask.register_blueprint` to register all views - and callbacks registered on the blueprint with the application. Creates - a :class:`.BlueprintSetupState` and calls each :meth:`record` callback - with it. - - :param app: The application this blueprint is being registered with. - :param options: Keyword arguments forwarded from - :meth:`~Flask.register_blueprint`. - :param first_registration: Whether this is the first time this - blueprint has been registered on the application. - """ - self._got_registered_once = True - state = self.make_setup_state(app, options, first_registration) - - if self.has_static_folder: - state.add_url_rule( - self.static_url_path + "/", - view_func=self.send_static_file, - endpoint="static", - ) - - for deferred in self.deferred_functions: - deferred(state) - - cli_resolved_group = options.get("cli_group", self.cli_group) - - if not self.cli.commands: - return - - if cli_resolved_group is None: - app.cli.commands.update(self.cli.commands) - elif cli_resolved_group is _sentinel: - self.cli.name = self.name - app.cli.add_command(self.cli) - else: - self.cli.name = cli_resolved_group - app.cli.add_command(self.cli) - - def route(self, rule, **options): - """Like :meth:`Flask.route` but for a blueprint. The endpoint for the - :func:`url_for` function is prefixed with the name of the blueprint. - """ - - def decorator(f): - endpoint = options.pop("endpoint", f.__name__) - self.add_url_rule(rule, endpoint, f, **options) - return f - - return decorator - - def add_url_rule(self, rule, endpoint=None, view_func=None, **options): - """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for - the :func:`url_for` function is prefixed with the name of the blueprint. - """ - if endpoint: - assert "." not in endpoint, "Blueprint endpoints should not contain dots" - if view_func and hasattr(view_func, "__name__"): - assert ( - "." not in view_func.__name__ - ), "Blueprint view function name should not contain dots" - self.record(lambda s: s.add_url_rule(rule, endpoint, view_func, **options)) - - def endpoint(self, endpoint): - """Like :meth:`Flask.endpoint` but for a blueprint. This does not - prefix the endpoint with the blueprint name, this has to be done - explicitly by the user of this method. If the endpoint is prefixed - with a `.` it will be registered to the current blueprint, otherwise - it's an application independent endpoint. - """ - - def decorator(f): - def register_endpoint(state): - state.app.view_functions[endpoint] = f - - self.record_once(register_endpoint) - return f - - return decorator - - def app_template_filter(self, name=None): - """Register a custom template filter, available application wide. Like - :meth:`Flask.template_filter` but for a blueprint. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_app_template_filter(f, name=name) - return f - - return decorator - - def add_app_template_filter(self, f, name=None): - """Register a custom template filter, available application wide. Like - :meth:`Flask.add_template_filter` but for a blueprint. Works exactly - like the :meth:`app_template_filter` decorator. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def register_template(state): - state.app.jinja_env.filters[name or f.__name__] = f - - self.record_once(register_template) - - def app_template_test(self, name=None): - """Register a custom template test, available application wide. Like - :meth:`Flask.template_test` but for a blueprint. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_app_template_test(f, name=name) - return f - - return decorator - - def add_app_template_test(self, f, name=None): - """Register a custom template test, available application wide. Like - :meth:`Flask.add_template_test` but for a blueprint. Works exactly - like the :meth:`app_template_test` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def register_template(state): - state.app.jinja_env.tests[name or f.__name__] = f - - self.record_once(register_template) - - def app_template_global(self, name=None): - """Register a custom template global, available application wide. Like - :meth:`Flask.template_global` but for a blueprint. - - .. versionadded:: 0.10 - - :param name: the optional name of the global, otherwise the - function name will be used. - """ - - def decorator(f): - self.add_app_template_global(f, name=name) - return f - - return decorator - - def add_app_template_global(self, f, name=None): - """Register a custom template global, available application wide. Like - :meth:`Flask.add_template_global` but for a blueprint. Works exactly - like the :meth:`app_template_global` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the global, otherwise the - function name will be used. - """ - - def register_template(state): - state.app.jinja_env.globals[name or f.__name__] = f - - self.record_once(register_template) - - def before_request(self, f): - """Like :meth:`Flask.before_request` but for a blueprint. This function - is only executed before each request that is handled by a function of - that blueprint. - """ - self.record_once( - lambda s: s.app.before_request_funcs.setdefault(self.name, []).append(f) - ) - return f - - def before_app_request(self, f): - """Like :meth:`Flask.before_request`. Such a function is executed - before each request, even if outside of a blueprint. - """ - self.record_once( - lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) - ) - return f - - def before_app_first_request(self, f): - """Like :meth:`Flask.before_first_request`. Such a function is - executed before the first request to the application. - """ - self.record_once(lambda s: s.app.before_first_request_funcs.append(f)) - return f - - def after_request(self, f): - """Like :meth:`Flask.after_request` but for a blueprint. This function - is only executed after each request that is handled by a function of - that blueprint. - """ - self.record_once( - lambda s: s.app.after_request_funcs.setdefault(self.name, []).append(f) - ) - return f - - def after_app_request(self, f): - """Like :meth:`Flask.after_request` but for a blueprint. Such a function - is executed after each request, even if outside of the blueprint. - """ - self.record_once( - lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) - ) - return f - - def teardown_request(self, f): - """Like :meth:`Flask.teardown_request` but for a blueprint. This - function is only executed when tearing down requests handled by a - function of that blueprint. Teardown request functions are executed - when the request context is popped, even when no actual request was - performed. - """ - self.record_once( - lambda s: s.app.teardown_request_funcs.setdefault(self.name, []).append(f) - ) - return f - - def teardown_app_request(self, f): - """Like :meth:`Flask.teardown_request` but for a blueprint. Such a - function is executed when tearing down each request, even if outside of - the blueprint. - """ - self.record_once( - lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) - ) - return f - - def context_processor(self, f): - """Like :meth:`Flask.context_processor` but for a blueprint. This - function is only executed for requests handled by a blueprint. - """ - self.record_once( - lambda s: s.app.template_context_processors.setdefault( - self.name, [] - ).append(f) - ) - return f - - def app_context_processor(self, f): - """Like :meth:`Flask.context_processor` but for a blueprint. Such a - function is executed each request, even if outside of the blueprint. - """ - self.record_once( - lambda s: s.app.template_context_processors.setdefault(None, []).append(f) - ) - return f - - def app_errorhandler(self, code): - """Like :meth:`Flask.errorhandler` but for a blueprint. This - handler is used for all requests, even if outside of the blueprint. - """ - - def decorator(f): - self.record_once(lambda s: s.app.errorhandler(code)(f)) - return f - - return decorator - - def url_value_preprocessor(self, f): - """Registers a function as URL value preprocessor for this - blueprint. It's called before the view functions are called and - can modify the url values provided. - """ - self.record_once( - lambda s: s.app.url_value_preprocessors.setdefault(self.name, []).append(f) - ) - return f - - def url_defaults(self, f): - """Callback function for URL defaults for this blueprint. It's called - with the endpoint and values and should update the values passed - in place. - """ - self.record_once( - lambda s: s.app.url_default_functions.setdefault(self.name, []).append(f) - ) - return f - - def app_url_value_preprocessor(self, f): - """Same as :meth:`url_value_preprocessor` but application wide. - """ - self.record_once( - lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) - ) - return f - - def app_url_defaults(self, f): - """Same as :meth:`url_defaults` but application wide. - """ - self.record_once( - lambda s: s.app.url_default_functions.setdefault(None, []).append(f) - ) - return f - - def errorhandler(self, code_or_exception): - """Registers an error handler that becomes active for this blueprint - only. Please be aware that routing does not happen local to a - blueprint so an error handler for 404 usually is not handled by - a blueprint unless it is caused inside a view function. Another - special case is the 500 internal server error which is always looked - up from the application. - - Otherwise works as the :meth:`~flask.Flask.errorhandler` decorator - of the :class:`~flask.Flask` object. - """ - - def decorator(f): - self.record_once( - lambda s: s.app._register_error_handler(self.name, code_or_exception, f) - ) - return f - - return decorator - - def register_error_handler(self, code_or_exception, f): - """Non-decorator version of the :meth:`errorhandler` error attach - function, akin to the :meth:`~flask.Flask.register_error_handler` - application-wide function of the :class:`~flask.Flask` object but - for error handlers limited to this blueprint. - - .. versionadded:: 0.11 - """ - self.record_once( - lambda s: s.app._register_error_handler(self.name, code_or_exception, f) - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/cli.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/cli.py deleted file mode 100644 index c09b2cd..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/cli.py +++ /dev/null @@ -1,971 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.cli - ~~~~~~~~~ - - A simple command line application to run flask apps. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -from __future__ import print_function - -import ast -import inspect -import os -import platform -import re -import sys -import traceback -from functools import update_wrapper -from operator import attrgetter -from threading import Lock -from threading import Thread - -import click -from werkzeug.utils import import_string - -from ._compat import getargspec -from ._compat import itervalues -from ._compat import reraise -from ._compat import text_type -from .globals import current_app -from .helpers import get_debug_flag -from .helpers import get_env -from .helpers import get_load_dotenv - -try: - import dotenv -except ImportError: - dotenv = None - -try: - import ssl -except ImportError: - ssl = None - - -class NoAppException(click.UsageError): - """Raised if an application cannot be found or loaded.""" - - -def find_best_app(script_info, module): - """Given a module instance this tries to find the best possible - application in the module or raises an exception. - """ - from . import Flask - - # Search for the most common names first. - for attr_name in ("app", "application"): - app = getattr(module, attr_name, None) - - if isinstance(app, Flask): - return app - - # Otherwise find the only object that is a Flask instance. - matches = [v for v in itervalues(module.__dict__) if isinstance(v, Flask)] - - if len(matches) == 1: - return matches[0] - elif len(matches) > 1: - raise NoAppException( - 'Detected multiple Flask applications in module "{module}". Use ' - '"FLASK_APP={module}:name" to specify the correct ' - "one.".format(module=module.__name__) - ) - - # Search for app factory functions. - for attr_name in ("create_app", "make_app"): - app_factory = getattr(module, attr_name, None) - - if inspect.isfunction(app_factory): - try: - app = call_factory(script_info, app_factory) - - if isinstance(app, Flask): - return app - except TypeError: - if not _called_with_wrong_args(app_factory): - raise - raise NoAppException( - 'Detected factory "{factory}" in module "{module}", but ' - "could not call it without arguments. Use " - "\"FLASK_APP='{module}:{factory}(args)'\" to specify " - "arguments.".format(factory=attr_name, module=module.__name__) - ) - - raise NoAppException( - 'Failed to find Flask application or factory in module "{module}". ' - 'Use "FLASK_APP={module}:name to specify one.'.format(module=module.__name__) - ) - - -def call_factory(script_info, app_factory, arguments=()): - """Takes an app factory, a ``script_info` object and optionally a tuple - of arguments. Checks for the existence of a script_info argument and calls - the app_factory depending on that and the arguments provided. - """ - args_spec = getargspec(app_factory) - arg_names = args_spec.args - arg_defaults = args_spec.defaults - - if "script_info" in arg_names: - return app_factory(*arguments, script_info=script_info) - elif arguments: - return app_factory(*arguments) - elif not arguments and len(arg_names) == 1 and arg_defaults is None: - return app_factory(script_info) - - return app_factory() - - -def _called_with_wrong_args(factory): - """Check whether calling a function raised a ``TypeError`` because - the call failed or because something in the factory raised the - error. - - :param factory: the factory function that was called - :return: true if the call failed - """ - tb = sys.exc_info()[2] - - try: - while tb is not None: - if tb.tb_frame.f_code is factory.__code__: - # in the factory, it was called successfully - return False - - tb = tb.tb_next - - # didn't reach the factory - return True - finally: - # explicitly delete tb as it is circular referenced - # https://docs.python.org/2/library/sys.html#sys.exc_info - del tb - - -def find_app_by_string(script_info, module, app_name): - """Checks if the given string is a variable name or a function. If it is a - function, it checks for specified arguments and whether it takes a - ``script_info`` argument and calls the function with the appropriate - arguments. - """ - from . import Flask - - match = re.match(r"^ *([^ ()]+) *(?:\((.*?) *,? *\))? *$", app_name) - - if not match: - raise NoAppException( - '"{name}" is not a valid variable name or function ' - "expression.".format(name=app_name) - ) - - name, args = match.groups() - - try: - attr = getattr(module, name) - except AttributeError as e: - raise NoAppException(e.args[0]) - - if inspect.isfunction(attr): - if args: - try: - args = ast.literal_eval("({args},)".format(args=args)) - except (ValueError, SyntaxError) as e: - raise NoAppException( - "Could not parse the arguments in " - '"{app_name}".'.format(e=e, app_name=app_name) - ) - else: - args = () - - try: - app = call_factory(script_info, attr, args) - except TypeError as e: - if not _called_with_wrong_args(attr): - raise - - raise NoAppException( - '{e}\nThe factory "{app_name}" in module "{module}" could not ' - "be called with the specified arguments.".format( - e=e, app_name=app_name, module=module.__name__ - ) - ) - else: - app = attr - - if isinstance(app, Flask): - return app - - raise NoAppException( - "A valid Flask application was not obtained from " - '"{module}:{app_name}".'.format(module=module.__name__, app_name=app_name) - ) - - -def prepare_import(path): - """Given a filename this will try to calculate the python path, add it - to the search path and return the actual module name that is expected. - """ - path = os.path.realpath(path) - - fname, ext = os.path.splitext(path) - if ext == ".py": - path = fname - - if os.path.basename(path) == "__init__": - path = os.path.dirname(path) - - module_name = [] - - # move up until outside package structure (no __init__.py) - while True: - path, name = os.path.split(path) - module_name.append(name) - - if not os.path.exists(os.path.join(path, "__init__.py")): - break - - if sys.path[0] != path: - sys.path.insert(0, path) - - return ".".join(module_name[::-1]) - - -def locate_app(script_info, module_name, app_name, raise_if_not_found=True): - __traceback_hide__ = True # noqa: F841 - - try: - __import__(module_name) - except ImportError: - # Reraise the ImportError if it occurred within the imported module. - # Determine this by checking whether the trace has a depth > 1. - if sys.exc_info()[-1].tb_next: - raise NoAppException( - 'While importing "{name}", an ImportError was raised:' - "\n\n{tb}".format(name=module_name, tb=traceback.format_exc()) - ) - elif raise_if_not_found: - raise NoAppException('Could not import "{name}".'.format(name=module_name)) - else: - return - - module = sys.modules[module_name] - - if app_name is None: - return find_best_app(script_info, module) - else: - return find_app_by_string(script_info, module, app_name) - - -def get_version(ctx, param, value): - if not value or ctx.resilient_parsing: - return - - import werkzeug - from . import __version__ - - message = "Python %(python)s\nFlask %(flask)s\nWerkzeug %(werkzeug)s" - click.echo( - message - % { - "python": platform.python_version(), - "flask": __version__, - "werkzeug": werkzeug.__version__, - }, - color=ctx.color, - ) - ctx.exit() - - -version_option = click.Option( - ["--version"], - help="Show the flask version", - expose_value=False, - callback=get_version, - is_flag=True, - is_eager=True, -) - - -class DispatchingApp(object): - """Special application that dispatches to a Flask application which - is imported by name in a background thread. If an error happens - it is recorded and shown as part of the WSGI handling which in case - of the Werkzeug debugger means that it shows up in the browser. - """ - - def __init__(self, loader, use_eager_loading=False): - self.loader = loader - self._app = None - self._lock = Lock() - self._bg_loading_exc_info = None - if use_eager_loading: - self._load_unlocked() - else: - self._load_in_background() - - def _load_in_background(self): - def _load_app(): - __traceback_hide__ = True # noqa: F841 - with self._lock: - try: - self._load_unlocked() - except Exception: - self._bg_loading_exc_info = sys.exc_info() - - t = Thread(target=_load_app, args=()) - t.start() - - def _flush_bg_loading_exception(self): - __traceback_hide__ = True # noqa: F841 - exc_info = self._bg_loading_exc_info - if exc_info is not None: - self._bg_loading_exc_info = None - reraise(*exc_info) - - def _load_unlocked(self): - __traceback_hide__ = True # noqa: F841 - self._app = rv = self.loader() - self._bg_loading_exc_info = None - return rv - - def __call__(self, environ, start_response): - __traceback_hide__ = True # noqa: F841 - if self._app is not None: - return self._app(environ, start_response) - self._flush_bg_loading_exception() - with self._lock: - if self._app is not None: - rv = self._app - else: - rv = self._load_unlocked() - return rv(environ, start_response) - - -class ScriptInfo(object): - """Helper object to deal with Flask applications. This is usually not - necessary to interface with as it's used internally in the dispatching - to click. In future versions of Flask this object will most likely play - a bigger role. Typically it's created automatically by the - :class:`FlaskGroup` but you can also manually create it and pass it - onwards as click object. - """ - - def __init__(self, app_import_path=None, create_app=None, set_debug_flag=True): - #: Optionally the import path for the Flask application. - self.app_import_path = app_import_path or os.environ.get("FLASK_APP") - #: Optionally a function that is passed the script info to create - #: the instance of the application. - self.create_app = create_app - #: A dictionary with arbitrary data that can be associated with - #: this script info. - self.data = {} - self.set_debug_flag = set_debug_flag - self._loaded_app = None - - def load_app(self): - """Loads the Flask app (if not yet loaded) and returns it. Calling - this multiple times will just result in the already loaded app to - be returned. - """ - __traceback_hide__ = True # noqa: F841 - - if self._loaded_app is not None: - return self._loaded_app - - app = None - - if self.create_app is not None: - app = call_factory(self, self.create_app) - else: - if self.app_import_path: - path, name = ( - re.split(r":(?![\\/])", self.app_import_path, 1) + [None] - )[:2] - import_name = prepare_import(path) - app = locate_app(self, import_name, name) - else: - for path in ("wsgi.py", "app.py"): - import_name = prepare_import(path) - app = locate_app(self, import_name, None, raise_if_not_found=False) - - if app: - break - - if not app: - raise NoAppException( - "Could not locate a Flask application. You did not provide " - 'the "FLASK_APP" environment variable, and a "wsgi.py" or ' - '"app.py" module was not found in the current directory.' - ) - - if self.set_debug_flag: - # Update the app's debug flag through the descriptor so that - # other values repopulate as well. - app.debug = get_debug_flag() - - self._loaded_app = app - return app - - -pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) - - -def with_appcontext(f): - """Wraps a callback so that it's guaranteed to be executed with the - script's application context. If callbacks are registered directly - to the ``app.cli`` object then they are wrapped with this function - by default unless it's disabled. - """ - - @click.pass_context - def decorator(__ctx, *args, **kwargs): - with __ctx.ensure_object(ScriptInfo).load_app().app_context(): - return __ctx.invoke(f, *args, **kwargs) - - return update_wrapper(decorator, f) - - -class AppGroup(click.Group): - """This works similar to a regular click :class:`~click.Group` but it - changes the behavior of the :meth:`command` decorator so that it - automatically wraps the functions in :func:`with_appcontext`. - - Not to be confused with :class:`FlaskGroup`. - """ - - def command(self, *args, **kwargs): - """This works exactly like the method of the same name on a regular - :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` - unless it's disabled by passing ``with_appcontext=False``. - """ - wrap_for_ctx = kwargs.pop("with_appcontext", True) - - def decorator(f): - if wrap_for_ctx: - f = with_appcontext(f) - return click.Group.command(self, *args, **kwargs)(f) - - return decorator - - def group(self, *args, **kwargs): - """This works exactly like the method of the same name on a regular - :class:`click.Group` but it defaults the group class to - :class:`AppGroup`. - """ - kwargs.setdefault("cls", AppGroup) - return click.Group.group(self, *args, **kwargs) - - -class FlaskGroup(AppGroup): - """Special subclass of the :class:`AppGroup` group that supports - loading more commands from the configured Flask app. Normally a - developer does not have to interface with this class but there are - some very advanced use cases for which it makes sense to create an - instance of this. - - For information as of why this is useful see :ref:`custom-scripts`. - - :param add_default_commands: if this is True then the default run and - shell commands will be added. - :param add_version_option: adds the ``--version`` option. - :param create_app: an optional callback that is passed the script info and - returns the loaded app. - :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` - files to set environment variables. Will also change the working - directory to the directory containing the first file found. - :param set_debug_flag: Set the app's debug flag based on the active - environment - - .. versionchanged:: 1.0 - If installed, python-dotenv will be used to load environment variables - from :file:`.env` and :file:`.flaskenv` files. - """ - - def __init__( - self, - add_default_commands=True, - create_app=None, - add_version_option=True, - load_dotenv=True, - set_debug_flag=True, - **extra - ): - params = list(extra.pop("params", None) or ()) - - if add_version_option: - params.append(version_option) - - AppGroup.__init__(self, params=params, **extra) - self.create_app = create_app - self.load_dotenv = load_dotenv - self.set_debug_flag = set_debug_flag - - if add_default_commands: - self.add_command(run_command) - self.add_command(shell_command) - self.add_command(routes_command) - - self._loaded_plugin_commands = False - - def _load_plugin_commands(self): - if self._loaded_plugin_commands: - return - try: - import pkg_resources - except ImportError: - self._loaded_plugin_commands = True - return - - for ep in pkg_resources.iter_entry_points("flask.commands"): - self.add_command(ep.load(), ep.name) - self._loaded_plugin_commands = True - - def get_command(self, ctx, name): - self._load_plugin_commands() - - # We load built-in commands first as these should always be the - # same no matter what the app does. If the app does want to - # override this it needs to make a custom instance of this group - # and not attach the default commands. - # - # This also means that the script stays functional in case the - # application completely fails. - rv = AppGroup.get_command(self, ctx, name) - if rv is not None: - return rv - - info = ctx.ensure_object(ScriptInfo) - try: - rv = info.load_app().cli.get_command(ctx, name) - if rv is not None: - return rv - except NoAppException: - pass - - def list_commands(self, ctx): - self._load_plugin_commands() - - # The commands available is the list of both the application (if - # available) plus the builtin commands. - rv = set(click.Group.list_commands(self, ctx)) - info = ctx.ensure_object(ScriptInfo) - try: - rv.update(info.load_app().cli.list_commands(ctx)) - except Exception: - # Here we intentionally swallow all exceptions as we don't - # want the help page to break if the app does not exist. - # If someone attempts to use the command we try to create - # the app again and this will give us the error. - # However, we will not do so silently because that would confuse - # users. - traceback.print_exc() - return sorted(rv) - - def main(self, *args, **kwargs): - # Set a global flag that indicates that we were invoked from the - # command line interface. This is detected by Flask.run to make the - # call into a no-op. This is necessary to avoid ugly errors when the - # script that is loaded here also attempts to start a server. - os.environ["FLASK_RUN_FROM_CLI"] = "true" - - if get_load_dotenv(self.load_dotenv): - load_dotenv() - - obj = kwargs.get("obj") - - if obj is None: - obj = ScriptInfo( - create_app=self.create_app, set_debug_flag=self.set_debug_flag - ) - - kwargs["obj"] = obj - kwargs.setdefault("auto_envvar_prefix", "FLASK") - return super(FlaskGroup, self).main(*args, **kwargs) - - -def _path_is_ancestor(path, other): - """Take ``other`` and remove the length of ``path`` from it. Then join it - to ``path``. If it is the original value, ``path`` is an ancestor of - ``other``.""" - return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other - - -def load_dotenv(path=None): - """Load "dotenv" files in order of precedence to set environment variables. - - If an env var is already set it is not overwritten, so earlier files in the - list are preferred over later files. - - Changes the current working directory to the location of the first file - found, with the assumption that it is in the top level project directory - and will be where the Python path should import local packages from. - - This is a no-op if `python-dotenv`_ is not installed. - - .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme - - :param path: Load the file at this location instead of searching. - :return: ``True`` if a file was loaded. - - .. versionchanged:: 1.1.0 - Returns ``False`` when python-dotenv is not installed, or when - the given path isn't a file. - - .. versionadded:: 1.0 - """ - if dotenv is None: - if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): - click.secho( - " * Tip: There are .env or .flaskenv files present." - ' Do "pip install python-dotenv" to use them.', - fg="yellow", - err=True, - ) - - return False - - # if the given path specifies the actual file then return True, - # else False - if path is not None: - if os.path.isfile(path): - return dotenv.load_dotenv(path) - - return False - - new_dir = None - - for name in (".env", ".flaskenv"): - path = dotenv.find_dotenv(name, usecwd=True) - - if not path: - continue - - if new_dir is None: - new_dir = os.path.dirname(path) - - dotenv.load_dotenv(path) - - if new_dir and os.getcwd() != new_dir: - os.chdir(new_dir) - - return new_dir is not None # at least one file was located and loaded - - -def show_server_banner(env, debug, app_import_path, eager_loading): - """Show extra startup messages the first time the server is run, - ignoring the reloader. - """ - if os.environ.get("WERKZEUG_RUN_MAIN") == "true": - return - - if app_import_path is not None: - message = ' * Serving Flask app "{0}"'.format(app_import_path) - - if not eager_loading: - message += " (lazy loading)" - - click.echo(message) - - click.echo(" * Environment: {0}".format(env)) - - if env == "production": - click.secho( - " WARNING: This is a development server. " - "Do not use it in a production deployment.", - fg="red", - ) - click.secho(" Use a production WSGI server instead.", dim=True) - - if debug is not None: - click.echo(" * Debug mode: {0}".format("on" if debug else "off")) - - -class CertParamType(click.ParamType): - """Click option type for the ``--cert`` option. Allows either an - existing file, the string ``'adhoc'``, or an import for a - :class:`~ssl.SSLContext` object. - """ - - name = "path" - - def __init__(self): - self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) - - def convert(self, value, param, ctx): - if ssl is None: - raise click.BadParameter( - 'Using "--cert" requires Python to be compiled with SSL support.', - ctx, - param, - ) - - try: - return self.path_type(value, param, ctx) - except click.BadParameter: - value = click.STRING(value, param, ctx).lower() - - if value == "adhoc": - try: - import OpenSSL # noqa: F401 - except ImportError: - raise click.BadParameter( - "Using ad-hoc certificates requires pyOpenSSL.", ctx, param - ) - - return value - - obj = import_string(value, silent=True) - - if sys.version_info < (2, 7, 9): - if obj: - return obj - else: - if isinstance(obj, ssl.SSLContext): - return obj - - raise - - -def _validate_key(ctx, param, value): - """The ``--key`` option must be specified when ``--cert`` is a file. - Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. - """ - cert = ctx.params.get("cert") - is_adhoc = cert == "adhoc" - - if sys.version_info < (2, 7, 9): - is_context = cert and not isinstance(cert, (text_type, bytes)) - else: - is_context = isinstance(cert, ssl.SSLContext) - - if value is not None: - if is_adhoc: - raise click.BadParameter( - 'When "--cert" is "adhoc", "--key" is not used.', ctx, param - ) - - if is_context: - raise click.BadParameter( - 'When "--cert" is an SSLContext object, "--key is not used.', ctx, param - ) - - if not cert: - raise click.BadParameter('"--cert" must also be specified.', ctx, param) - - ctx.params["cert"] = cert, value - - else: - if cert and not (is_adhoc or is_context): - raise click.BadParameter('Required when using "--cert".', ctx, param) - - return value - - -class SeparatedPathType(click.Path): - """Click option type that accepts a list of values separated by the - OS's path separator (``:``, ``;`` on Windows). Each value is - validated as a :class:`click.Path` type. - """ - - def convert(self, value, param, ctx): - items = self.split_envvar_value(value) - super_convert = super(SeparatedPathType, self).convert - return [super_convert(item, param, ctx) for item in items] - - -@click.command("run", short_help="Run a development server.") -@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") -@click.option("--port", "-p", default=5000, help="The port to bind to.") -@click.option( - "--cert", type=CertParamType(), help="Specify a certificate file to use HTTPS." -) -@click.option( - "--key", - type=click.Path(exists=True, dir_okay=False, resolve_path=True), - callback=_validate_key, - expose_value=False, - help="The key file to use when specifying a certificate.", -) -@click.option( - "--reload/--no-reload", - default=None, - help="Enable or disable the reloader. By default the reloader " - "is active if debug is enabled.", -) -@click.option( - "--debugger/--no-debugger", - default=None, - help="Enable or disable the debugger. By default the debugger " - "is active if debug is enabled.", -) -@click.option( - "--eager-loading/--lazy-loader", - default=None, - help="Enable or disable eager loading. By default eager " - "loading is enabled if the reloader is disabled.", -) -@click.option( - "--with-threads/--without-threads", - default=True, - help="Enable or disable multithreading.", -) -@click.option( - "--extra-files", - default=None, - type=SeparatedPathType(), - help=( - "Extra files that trigger a reload on change. Multiple paths" - " are separated by '{}'.".format(os.path.pathsep) - ), -) -@pass_script_info -def run_command( - info, host, port, reload, debugger, eager_loading, with_threads, cert, extra_files -): - """Run a local development server. - - This server is for development purposes only. It does not provide - the stability, security, or performance of production WSGI servers. - - The reloader and debugger are enabled by default if - FLASK_ENV=development or FLASK_DEBUG=1. - """ - debug = get_debug_flag() - - if reload is None: - reload = debug - - if debugger is None: - debugger = debug - - if eager_loading is None: - eager_loading = not reload - - show_server_banner(get_env(), debug, info.app_import_path, eager_loading) - app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) - - from werkzeug.serving import run_simple - - run_simple( - host, - port, - app, - use_reloader=reload, - use_debugger=debugger, - threaded=with_threads, - ssl_context=cert, - extra_files=extra_files, - ) - - -@click.command("shell", short_help="Run a shell in the app context.") -@with_appcontext -def shell_command(): - """Run an interactive Python shell in the context of a given - Flask application. The application will populate the default - namespace of this shell according to it's configuration. - - This is useful for executing small snippets of management code - without having to manually configure the application. - """ - import code - from .globals import _app_ctx_stack - - app = _app_ctx_stack.top.app - banner = "Python %s on %s\nApp: %s [%s]\nInstance: %s" % ( - sys.version, - sys.platform, - app.import_name, - app.env, - app.instance_path, - ) - ctx = {} - - # Support the regular Python interpreter startup script if someone - # is using it. - startup = os.environ.get("PYTHONSTARTUP") - if startup and os.path.isfile(startup): - with open(startup, "r") as f: - eval(compile(f.read(), startup, "exec"), ctx) - - ctx.update(app.make_shell_context()) - - code.interact(banner=banner, local=ctx) - - -@click.command("routes", short_help="Show the routes for the app.") -@click.option( - "--sort", - "-s", - type=click.Choice(("endpoint", "methods", "rule", "match")), - default="endpoint", - help=( - 'Method to sort routes by. "match" is the order that Flask will match ' - "routes when dispatching a request." - ), -) -@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") -@with_appcontext -def routes_command(sort, all_methods): - """Show all registered routes with endpoints and methods.""" - - rules = list(current_app.url_map.iter_rules()) - if not rules: - click.echo("No routes were registered.") - return - - ignored_methods = set(() if all_methods else ("HEAD", "OPTIONS")) - - if sort in ("endpoint", "rule"): - rules = sorted(rules, key=attrgetter(sort)) - elif sort == "methods": - rules = sorted(rules, key=lambda rule: sorted(rule.methods)) - - rule_methods = [", ".join(sorted(rule.methods - ignored_methods)) for rule in rules] - - headers = ("Endpoint", "Methods", "Rule") - widths = ( - max(len(rule.endpoint) for rule in rules), - max(len(methods) for methods in rule_methods), - max(len(rule.rule) for rule in rules), - ) - widths = [max(len(h), w) for h, w in zip(headers, widths)] - row = "{{0:<{0}}} {{1:<{1}}} {{2:<{2}}}".format(*widths) - - click.echo(row.format(*headers).strip()) - click.echo(row.format(*("-" * width for width in widths))) - - for rule, methods in zip(rules, rule_methods): - click.echo(row.format(rule.endpoint, methods, rule.rule).rstrip()) - - -cli = FlaskGroup( - help="""\ -A general utility script for Flask applications. - -Provides commands from Flask, extensions, and the application. Loads the -application defined in the FLASK_APP environment variable, or from a wsgi.py -file. Setting the FLASK_ENV environment variable to 'development' will enable -debug mode. - -\b - {prefix}{cmd} FLASK_APP=hello.py - {prefix}{cmd} FLASK_ENV=development - {prefix}flask run -""".format( - cmd="export" if os.name == "posix" else "set", - prefix="$ " if os.name == "posix" else "> ", - ) -) - - -def main(as_module=False): - # TODO omit sys.argv once https://github.com/pallets/click/issues/536 is fixed - cli.main(args=sys.argv[1:], prog_name="python -m flask" if as_module else None) - - -if __name__ == "__main__": - main(as_module=True) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/config.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/config.py deleted file mode 100644 index 809de33..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/config.py +++ /dev/null @@ -1,269 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.config - ~~~~~~~~~~~~ - - Implements the configuration related objects. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import errno -import os -import types - -from werkzeug.utils import import_string - -from . import json -from ._compat import iteritems -from ._compat import string_types - - -class ConfigAttribute(object): - """Makes an attribute forward to the config""" - - def __init__(self, name, get_converter=None): - self.__name__ = name - self.get_converter = get_converter - - def __get__(self, obj, type=None): - if obj is None: - return self - rv = obj.config[self.__name__] - if self.get_converter is not None: - rv = self.get_converter(rv) - return rv - - def __set__(self, obj, value): - obj.config[self.__name__] = value - - -class Config(dict): - """Works exactly like a dict but provides ways to fill it from files - or special dictionaries. There are two common patterns to populate the - config. - - Either you can fill the config from a config file:: - - app.config.from_pyfile('yourconfig.cfg') - - Or alternatively you can define the configuration options in the - module that calls :meth:`from_object` or provide an import path to - a module that should be loaded. It is also possible to tell it to - use the same module and with that provide the configuration values - just before the call:: - - DEBUG = True - SECRET_KEY = 'development key' - app.config.from_object(__name__) - - In both cases (loading from any Python file or loading from modules), - only uppercase keys are added to the config. This makes it possible to use - lowercase values in the config file for temporary values that are not added - to the config or to define the config keys in the same file that implements - the application. - - Probably the most interesting way to load configurations is from an - environment variable pointing to a file:: - - app.config.from_envvar('YOURAPPLICATION_SETTINGS') - - In this case before launching the application you have to set this - environment variable to the file you want to use. On Linux and OS X - use the export statement:: - - export YOURAPPLICATION_SETTINGS='/path/to/config/file' - - On windows use `set` instead. - - :param root_path: path to which files are read relative from. When the - config object is created by the application, this is - the application's :attr:`~flask.Flask.root_path`. - :param defaults: an optional dictionary of default values - """ - - def __init__(self, root_path, defaults=None): - dict.__init__(self, defaults or {}) - self.root_path = root_path - - def from_envvar(self, variable_name, silent=False): - """Loads a configuration from an environment variable pointing to - a configuration file. This is basically just a shortcut with nicer - error messages for this line of code:: - - app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) - - :param variable_name: name of the environment variable - :param silent: set to ``True`` if you want silent failure for missing - files. - :return: bool. ``True`` if able to load config, ``False`` otherwise. - """ - rv = os.environ.get(variable_name) - if not rv: - if silent: - return False - raise RuntimeError( - "The environment variable %r is not set " - "and as such configuration could not be " - "loaded. Set this variable and make it " - "point to a configuration file" % variable_name - ) - return self.from_pyfile(rv, silent=silent) - - def from_pyfile(self, filename, silent=False): - """Updates the values in the config from a Python file. This function - behaves as if the file was imported as module with the - :meth:`from_object` function. - - :param filename: the filename of the config. This can either be an - absolute filename or a filename relative to the - root path. - :param silent: set to ``True`` if you want silent failure for missing - files. - - .. versionadded:: 0.7 - `silent` parameter. - """ - filename = os.path.join(self.root_path, filename) - d = types.ModuleType("config") - d.__file__ = filename - try: - with open(filename, mode="rb") as config_file: - exec(compile(config_file.read(), filename, "exec"), d.__dict__) - except IOError as e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): - return False - e.strerror = "Unable to load configuration file (%s)" % e.strerror - raise - self.from_object(d) - return True - - def from_object(self, obj): - """Updates the values from the given object. An object can be of one - of the following two types: - - - a string: in this case the object with that name will be imported - - an actual object reference: that object is used directly - - Objects are usually either modules or classes. :meth:`from_object` - loads only the uppercase attributes of the module/class. A ``dict`` - object will not work with :meth:`from_object` because the keys of a - ``dict`` are not attributes of the ``dict`` class. - - Example of module-based configuration:: - - app.config.from_object('yourapplication.default_config') - from yourapplication import default_config - app.config.from_object(default_config) - - Nothing is done to the object before loading. If the object is a - class and has ``@property`` attributes, it needs to be - instantiated before being passed to this method. - - You should not use this function to load the actual configuration but - rather configuration defaults. The actual config should be loaded - with :meth:`from_pyfile` and ideally from a location not within the - package because the package might be installed system wide. - - See :ref:`config-dev-prod` for an example of class-based configuration - using :meth:`from_object`. - - :param obj: an import name or object - """ - if isinstance(obj, string_types): - obj = import_string(obj) - for key in dir(obj): - if key.isupper(): - self[key] = getattr(obj, key) - - def from_json(self, filename, silent=False): - """Updates the values in the config from a JSON file. This function - behaves as if the JSON object was a dictionary and passed to the - :meth:`from_mapping` function. - - :param filename: the filename of the JSON file. This can either be an - absolute filename or a filename relative to the - root path. - :param silent: set to ``True`` if you want silent failure for missing - files. - - .. versionadded:: 0.11 - """ - filename = os.path.join(self.root_path, filename) - - try: - with open(filename) as json_file: - obj = json.loads(json_file.read()) - except IOError as e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR): - return False - e.strerror = "Unable to load configuration file (%s)" % e.strerror - raise - return self.from_mapping(obj) - - def from_mapping(self, *mapping, **kwargs): - """Updates the config like :meth:`update` ignoring items with non-upper - keys. - - .. versionadded:: 0.11 - """ - mappings = [] - if len(mapping) == 1: - if hasattr(mapping[0], "items"): - mappings.append(mapping[0].items()) - else: - mappings.append(mapping[0]) - elif len(mapping) > 1: - raise TypeError( - "expected at most 1 positional argument, got %d" % len(mapping) - ) - mappings.append(kwargs.items()) - for mapping in mappings: - for (key, value) in mapping: - if key.isupper(): - self[key] = value - return True - - def get_namespace(self, namespace, lowercase=True, trim_namespace=True): - """Returns a dictionary containing a subset of configuration options - that match the specified namespace/prefix. Example usage:: - - app.config['IMAGE_STORE_TYPE'] = 'fs' - app.config['IMAGE_STORE_PATH'] = '/var/app/images' - app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' - image_store_config = app.config.get_namespace('IMAGE_STORE_') - - The resulting dictionary `image_store_config` would look like:: - - { - 'type': 'fs', - 'path': '/var/app/images', - 'base_url': 'http://img.website.com' - } - - This is often useful when configuration options map directly to - keyword arguments in functions or class constructors. - - :param namespace: a configuration namespace - :param lowercase: a flag indicating if the keys of the resulting - dictionary should be lowercase - :param trim_namespace: a flag indicating if the keys of the resulting - dictionary should not include the namespace - - .. versionadded:: 0.11 - """ - rv = {} - for k, v in iteritems(self): - if not k.startswith(namespace): - continue - if trim_namespace: - key = k[len(namespace) :] - else: - key = k - if lowercase: - key = key.lower() - rv[key] = v - return rv - - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, dict.__repr__(self)) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/ctx.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/ctx.py deleted file mode 100644 index 172f6a0..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/ctx.py +++ /dev/null @@ -1,475 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.ctx - ~~~~~~~~~ - - Implements the objects required to keep the context. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import sys -from functools import update_wrapper - -from werkzeug.exceptions import HTTPException - -from ._compat import BROKEN_PYPY_CTXMGR_EXIT -from ._compat import reraise -from .globals import _app_ctx_stack -from .globals import _request_ctx_stack -from .signals import appcontext_popped -from .signals import appcontext_pushed - - -# a singleton sentinel value for parameter defaults -_sentinel = object() - - -class _AppCtxGlobals(object): - """A plain object. Used as a namespace for storing data during an - application context. - - Creating an app context automatically creates this object, which is - made available as the :data:`g` proxy. - - .. describe:: 'key' in g - - Check whether an attribute is present. - - .. versionadded:: 0.10 - - .. describe:: iter(g) - - Return an iterator over the attribute names. - - .. versionadded:: 0.10 - """ - - def get(self, name, default=None): - """Get an attribute by name, or a default value. Like - :meth:`dict.get`. - - :param name: Name of attribute to get. - :param default: Value to return if the attribute is not present. - - .. versionadded:: 0.10 - """ - return self.__dict__.get(name, default) - - def pop(self, name, default=_sentinel): - """Get and remove an attribute by name. Like :meth:`dict.pop`. - - :param name: Name of attribute to pop. - :param default: Value to return if the attribute is not present, - instead of raise a ``KeyError``. - - .. versionadded:: 0.11 - """ - if default is _sentinel: - return self.__dict__.pop(name) - else: - return self.__dict__.pop(name, default) - - def setdefault(self, name, default=None): - """Get the value of an attribute if it is present, otherwise - set and return a default value. Like :meth:`dict.setdefault`. - - :param name: Name of attribute to get. - :param: default: Value to set and return if the attribute is not - present. - - .. versionadded:: 0.11 - """ - return self.__dict__.setdefault(name, default) - - def __contains__(self, item): - return item in self.__dict__ - - def __iter__(self): - return iter(self.__dict__) - - def __repr__(self): - top = _app_ctx_stack.top - if top is not None: - return "" % top.app.name - return object.__repr__(self) - - -def after_this_request(f): - """Executes a function after this request. This is useful to modify - response objects. The function is passed the response object and has - to return the same or a new one. - - Example:: - - @app.route('/') - def index(): - @after_this_request - def add_header(response): - response.headers['X-Foo'] = 'Parachute' - return response - return 'Hello World!' - - This is more useful if a function other than the view function wants to - modify a response. For instance think of a decorator that wants to add - some headers without converting the return value into a response object. - - .. versionadded:: 0.9 - """ - _request_ctx_stack.top._after_request_functions.append(f) - return f - - -def copy_current_request_context(f): - """A helper function that decorates a function to retain the current - request context. This is useful when working with greenlets. The moment - the function is decorated a copy of the request context is created and - then pushed when the function is called. The current session is also - included in the copied request context. - - Example:: - - import gevent - from flask import copy_current_request_context - - @app.route('/') - def index(): - @copy_current_request_context - def do_some_work(): - # do some work here, it can access flask.request or - # flask.session like you would otherwise in the view function. - ... - gevent.spawn(do_some_work) - return 'Regular response' - - .. versionadded:: 0.10 - """ - top = _request_ctx_stack.top - if top is None: - raise RuntimeError( - "This decorator can only be used at local scopes " - "when a request context is on the stack. For instance within " - "view functions." - ) - reqctx = top.copy() - - def wrapper(*args, **kwargs): - with reqctx: - return f(*args, **kwargs) - - return update_wrapper(wrapper, f) - - -def has_request_context(): - """If you have code that wants to test if a request context is there or - not this function can be used. For instance, you may want to take advantage - of request information if the request object is available, but fail - silently if it is unavailable. - - :: - - class User(db.Model): - - def __init__(self, username, remote_addr=None): - self.username = username - if remote_addr is None and has_request_context(): - remote_addr = request.remote_addr - self.remote_addr = remote_addr - - Alternatively you can also just test any of the context bound objects - (such as :class:`request` or :class:`g`) for truthness:: - - class User(db.Model): - - def __init__(self, username, remote_addr=None): - self.username = username - if remote_addr is None and request: - remote_addr = request.remote_addr - self.remote_addr = remote_addr - - .. versionadded:: 0.7 - """ - return _request_ctx_stack.top is not None - - -def has_app_context(): - """Works like :func:`has_request_context` but for the application - context. You can also just do a boolean check on the - :data:`current_app` object instead. - - .. versionadded:: 0.9 - """ - return _app_ctx_stack.top is not None - - -class AppContext(object): - """The application context binds an application object implicitly - to the current thread or greenlet, similar to how the - :class:`RequestContext` binds request information. The application - context is also implicitly created if a request context is created - but the application is not on top of the individual application - context. - """ - - def __init__(self, app): - self.app = app - self.url_adapter = app.create_url_adapter(None) - self.g = app.app_ctx_globals_class() - - # Like request context, app contexts can be pushed multiple times - # but there a basic "refcount" is enough to track them. - self._refcnt = 0 - - def push(self): - """Binds the app context to the current context.""" - self._refcnt += 1 - if hasattr(sys, "exc_clear"): - sys.exc_clear() - _app_ctx_stack.push(self) - appcontext_pushed.send(self.app) - - def pop(self, exc=_sentinel): - """Pops the app context.""" - try: - self._refcnt -= 1 - if self._refcnt <= 0: - if exc is _sentinel: - exc = sys.exc_info()[1] - self.app.do_teardown_appcontext(exc) - finally: - rv = _app_ctx_stack.pop() - assert rv is self, "Popped wrong app context. (%r instead of %r)" % (rv, self) - appcontext_popped.send(self.app) - - def __enter__(self): - self.push() - return self - - def __exit__(self, exc_type, exc_value, tb): - self.pop(exc_value) - - if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None: - reraise(exc_type, exc_value, tb) - - -class RequestContext(object): - """The request context contains all request relevant information. It is - created at the beginning of the request and pushed to the - `_request_ctx_stack` and removed at the end of it. It will create the - URL adapter and request object for the WSGI environment provided. - - Do not attempt to use this class directly, instead use - :meth:`~flask.Flask.test_request_context` and - :meth:`~flask.Flask.request_context` to create this object. - - When the request context is popped, it will evaluate all the - functions registered on the application for teardown execution - (:meth:`~flask.Flask.teardown_request`). - - The request context is automatically popped at the end of the request - for you. In debug mode the request context is kept around if - exceptions happen so that interactive debuggers have a chance to - introspect the data. With 0.4 this can also be forced for requests - that did not fail and outside of ``DEBUG`` mode. By setting - ``'flask._preserve_context'`` to ``True`` on the WSGI environment the - context will not pop itself at the end of the request. This is used by - the :meth:`~flask.Flask.test_client` for example to implement the - deferred cleanup functionality. - - You might find this helpful for unittests where you need the - information from the context local around for a little longer. Make - sure to properly :meth:`~werkzeug.LocalStack.pop` the stack yourself in - that situation, otherwise your unittests will leak memory. - """ - - def __init__(self, app, environ, request=None, session=None): - self.app = app - if request is None: - request = app.request_class(environ) - self.request = request - self.url_adapter = None - try: - self.url_adapter = app.create_url_adapter(self.request) - except HTTPException as e: - self.request.routing_exception = e - self.flashes = None - self.session = session - - # Request contexts can be pushed multiple times and interleaved with - # other request contexts. Now only if the last level is popped we - # get rid of them. Additionally if an application context is missing - # one is created implicitly so for each level we add this information - self._implicit_app_ctx_stack = [] - - # indicator if the context was preserved. Next time another context - # is pushed the preserved context is popped. - self.preserved = False - - # remembers the exception for pop if there is one in case the context - # preservation kicks in. - self._preserved_exc = None - - # Functions that should be executed after the request on the response - # object. These will be called before the regular "after_request" - # functions. - self._after_request_functions = [] - - @property - def g(self): - return _app_ctx_stack.top.g - - @g.setter - def g(self, value): - _app_ctx_stack.top.g = value - - def copy(self): - """Creates a copy of this request context with the same request object. - This can be used to move a request context to a different greenlet. - Because the actual request object is the same this cannot be used to - move a request context to a different thread unless access to the - request object is locked. - - .. versionadded:: 0.10 - - .. versionchanged:: 1.1 - The current session object is used instead of reloading the original - data. This prevents `flask.session` pointing to an out-of-date object. - """ - return self.__class__( - self.app, - environ=self.request.environ, - request=self.request, - session=self.session, - ) - - def match_request(self): - """Can be overridden by a subclass to hook into the matching - of the request. - """ - try: - result = self.url_adapter.match(return_rule=True) - self.request.url_rule, self.request.view_args = result - except HTTPException as e: - self.request.routing_exception = e - - def push(self): - """Binds the request context to the current context.""" - # If an exception occurs in debug mode or if context preservation is - # activated under exception situations exactly one context stays - # on the stack. The rationale is that you want to access that - # information under debug situations. However if someone forgets to - # pop that context again we want to make sure that on the next push - # it's invalidated, otherwise we run at risk that something leaks - # memory. This is usually only a problem in test suite since this - # functionality is not active in production environments. - top = _request_ctx_stack.top - if top is not None and top.preserved: - top.pop(top._preserved_exc) - - # Before we push the request context we have to ensure that there - # is an application context. - app_ctx = _app_ctx_stack.top - if app_ctx is None or app_ctx.app != self.app: - app_ctx = self.app.app_context() - app_ctx.push() - self._implicit_app_ctx_stack.append(app_ctx) - else: - self._implicit_app_ctx_stack.append(None) - - if hasattr(sys, "exc_clear"): - sys.exc_clear() - - _request_ctx_stack.push(self) - - # Open the session at the moment that the request context is available. - # This allows a custom open_session method to use the request context. - # Only open a new session if this is the first time the request was - # pushed, otherwise stream_with_context loses the session. - if self.session is None: - session_interface = self.app.session_interface - self.session = session_interface.open_session(self.app, self.request) - - if self.session is None: - self.session = session_interface.make_null_session(self.app) - - if self.url_adapter is not None: - self.match_request() - - def pop(self, exc=_sentinel): - """Pops the request context and unbinds it by doing that. This will - also trigger the execution of functions registered by the - :meth:`~flask.Flask.teardown_request` decorator. - - .. versionchanged:: 0.9 - Added the `exc` argument. - """ - app_ctx = self._implicit_app_ctx_stack.pop() - - try: - clear_request = False - if not self._implicit_app_ctx_stack: - self.preserved = False - self._preserved_exc = None - if exc is _sentinel: - exc = sys.exc_info()[1] - self.app.do_teardown_request(exc) - - # If this interpreter supports clearing the exception information - # we do that now. This will only go into effect on Python 2.x, - # on 3.x it disappears automatically at the end of the exception - # stack. - if hasattr(sys, "exc_clear"): - sys.exc_clear() - - request_close = getattr(self.request, "close", None) - if request_close is not None: - request_close() - clear_request = True - finally: - rv = _request_ctx_stack.pop() - - # get rid of circular dependencies at the end of the request - # so that we don't require the GC to be active. - if clear_request: - rv.request.environ["werkzeug.request"] = None - - # Get rid of the app as well if necessary. - if app_ctx is not None: - app_ctx.pop(exc) - - assert rv is self, "Popped wrong request context. (%r instead of %r)" % ( - rv, - self, - ) - - def auto_pop(self, exc): - if self.request.environ.get("flask._preserve_context") or ( - exc is not None and self.app.preserve_context_on_exception - ): - self.preserved = True - self._preserved_exc = exc - else: - self.pop(exc) - - def __enter__(self): - self.push() - return self - - def __exit__(self, exc_type, exc_value, tb): - # do not pop the request stack if we are in debug mode and an - # exception happened. This will allow the debugger to still - # access the request object in the interactive shell. Furthermore - # the context can be force kept alive for the test client. - # See flask.testing for how this works. - self.auto_pop(exc_value) - - if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None: - reraise(exc_type, exc_value, tb) - - def __repr__(self): - return "<%s '%s' [%s] of %s>" % ( - self.__class__.__name__, - self.request.url, - self.request.method, - self.app.name, - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/debughelpers.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/debughelpers.py deleted file mode 100644 index e475bd1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/debughelpers.py +++ /dev/null @@ -1,183 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.debughelpers - ~~~~~~~~~~~~~~~~~~ - - Various helpers to make the development experience better. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import os -from warnings import warn - -from ._compat import implements_to_string -from ._compat import text_type -from .app import Flask -from .blueprints import Blueprint -from .globals import _request_ctx_stack - - -class UnexpectedUnicodeError(AssertionError, UnicodeError): - """Raised in places where we want some better error reporting for - unexpected unicode or binary data. - """ - - -@implements_to_string -class DebugFilesKeyError(KeyError, AssertionError): - """Raised from request.files during debugging. The idea is that it can - provide a better error message than just a generic KeyError/BadRequest. - """ - - def __init__(self, request, key): - form_matches = request.form.getlist(key) - buf = [ - 'You tried to access the file "%s" in the request.files ' - "dictionary but it does not exist. The mimetype for the request " - 'is "%s" instead of "multipart/form-data" which means that no ' - "file contents were transmitted. To fix this error you should " - 'provide enctype="multipart/form-data" in your form.' - % (key, request.mimetype) - ] - if form_matches: - buf.append( - "\n\nThe browser instead transmitted some file names. " - "This was submitted: %s" % ", ".join('"%s"' % x for x in form_matches) - ) - self.msg = "".join(buf) - - def __str__(self): - return self.msg - - -class FormDataRoutingRedirect(AssertionError): - """This exception is raised by Flask in debug mode if it detects a - redirect caused by the routing system when the request method is not - GET, HEAD or OPTIONS. Reasoning: form data will be dropped. - """ - - def __init__(self, request): - exc = request.routing_exception - buf = [ - "A request was sent to this URL (%s) but a redirect was " - 'issued automatically by the routing system to "%s".' - % (request.url, exc.new_url) - ] - - # In case just a slash was appended we can be extra helpful - if request.base_url + "/" == exc.new_url.split("?")[0]: - buf.append( - " The URL was defined with a trailing slash so " - "Flask will automatically redirect to the URL " - "with the trailing slash if it was accessed " - "without one." - ) - - buf.append( - " Make sure to directly send your %s-request to this URL " - "since we can't make browsers or HTTP clients redirect " - "with form data reliably or without user interaction." % request.method - ) - buf.append("\n\nNote: this exception is only raised in debug mode") - AssertionError.__init__(self, "".join(buf).encode("utf-8")) - - -def attach_enctype_error_multidict(request): - """Since Flask 0.8 we're monkeypatching the files object in case a - request is detected that does not use multipart form data but the files - object is accessed. - """ - oldcls = request.files.__class__ - - class newcls(oldcls): - def __getitem__(self, key): - try: - return oldcls.__getitem__(self, key) - except KeyError: - if key not in request.form: - raise - raise DebugFilesKeyError(request, key) - - newcls.__name__ = oldcls.__name__ - newcls.__module__ = oldcls.__module__ - request.files.__class__ = newcls - - -def _dump_loader_info(loader): - yield "class: %s.%s" % (type(loader).__module__, type(loader).__name__) - for key, value in sorted(loader.__dict__.items()): - if key.startswith("_"): - continue - if isinstance(value, (tuple, list)): - if not all(isinstance(x, (str, text_type)) for x in value): - continue - yield "%s:" % key - for item in value: - yield " - %s" % item - continue - elif not isinstance(value, (str, text_type, int, float, bool)): - continue - yield "%s: %r" % (key, value) - - -def explain_template_loading_attempts(app, template, attempts): - """This should help developers understand what failed""" - info = ['Locating template "%s":' % template] - total_found = 0 - blueprint = None - reqctx = _request_ctx_stack.top - if reqctx is not None and reqctx.request.blueprint is not None: - blueprint = reqctx.request.blueprint - - for idx, (loader, srcobj, triple) in enumerate(attempts): - if isinstance(srcobj, Flask): - src_info = 'application "%s"' % srcobj.import_name - elif isinstance(srcobj, Blueprint): - src_info = 'blueprint "%s" (%s)' % (srcobj.name, srcobj.import_name) - else: - src_info = repr(srcobj) - - info.append("% 5d: trying loader of %s" % (idx + 1, src_info)) - - for line in _dump_loader_info(loader): - info.append(" %s" % line) - - if triple is None: - detail = "no match" - else: - detail = "found (%r)" % (triple[1] or "") - total_found += 1 - info.append(" -> %s" % detail) - - seems_fishy = False - if total_found == 0: - info.append("Error: the template could not be found.") - seems_fishy = True - elif total_found > 1: - info.append("Warning: multiple loaders returned a match for the template.") - seems_fishy = True - - if blueprint is not None and seems_fishy: - info.append( - " The template was looked up from an endpoint that " - 'belongs to the blueprint "%s".' % blueprint - ) - info.append(" Maybe you did not place a template in the right folder?") - info.append(" See http://flask.pocoo.org/docs/blueprints/#templates") - - app.logger.info("\n".join(info)) - - -def explain_ignored_app_run(): - if os.environ.get("WERKZEUG_RUN_MAIN") != "true": - warn( - Warning( - "Silently ignoring app.run() because the " - "application is run from the flask command line " - "executable. Consider putting app.run() behind an " - 'if __name__ == "__main__" guard to silence this ' - "warning." - ), - stacklevel=3, - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/globals.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/globals.py deleted file mode 100644 index 6d32dcf..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/globals.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.globals - ~~~~~~~~~~~~~ - - Defines all the global objects that are proxies to the current - active context. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -from functools import partial - -from werkzeug.local import LocalProxy -from werkzeug.local import LocalStack - - -_request_ctx_err_msg = """\ -Working outside of request context. - -This typically means that you attempted to use functionality that needed -an active HTTP request. Consult the documentation on testing for -information about how to avoid this problem.\ -""" -_app_ctx_err_msg = """\ -Working outside of application context. - -This typically means that you attempted to use functionality that needed -to interface with the current application object in some way. To solve -this, set up an application context with app.app_context(). See the -documentation for more information.\ -""" - - -def _lookup_req_object(name): - top = _request_ctx_stack.top - if top is None: - raise RuntimeError(_request_ctx_err_msg) - return getattr(top, name) - - -def _lookup_app_object(name): - top = _app_ctx_stack.top - if top is None: - raise RuntimeError(_app_ctx_err_msg) - return getattr(top, name) - - -def _find_app(): - top = _app_ctx_stack.top - if top is None: - raise RuntimeError(_app_ctx_err_msg) - return top.app - - -# context locals -_request_ctx_stack = LocalStack() -_app_ctx_stack = LocalStack() -current_app = LocalProxy(_find_app) -request = LocalProxy(partial(_lookup_req_object, "request")) -session = LocalProxy(partial(_lookup_req_object, "session")) -g = LocalProxy(partial(_lookup_app_object, "g")) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/helpers.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/helpers.py deleted file mode 100644 index df06db8..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/helpers.py +++ /dev/null @@ -1,1155 +0,0 @@ -# -*- coding: utf-8 -*- -""" - flask.helpers - ~~~~~~~~~~~~~ - - Implements various helpers. - - :copyright: 2010 Pallets - :license: BSD-3-Clause -""" -import io -import mimetypes -import os -import pkgutil -import posixpath -import socket -import sys -import unicodedata -from functools import update_wrapper -from threading import RLock -from time import time -from zlib import adler32 - -from jinja2 import FileSystemLoader -from werkzeug.datastructures import Headers -from werkzeug.exceptions import BadRequest -from werkzeug.exceptions import NotFound -from werkzeug.exceptions import RequestedRangeNotSatisfiable -from werkzeug.routing import BuildError -from werkzeug.urls import url_quote -from werkzeug.wsgi import wrap_file - -from ._compat import fspath -from ._compat import PY2 -from ._compat import string_types -from ._compat import text_type -from .globals import _app_ctx_stack -from .globals import _request_ctx_stack -from .globals import current_app -from .globals import request -from .globals import session -from .signals import message_flashed - -# sentinel -_missing = object() - - -# what separators does this operating system provide that are not a slash? -# this is used by the send_from_directory function to ensure that nobody is -# able to access files from outside the filesystem. -_os_alt_seps = list( - sep for sep in [os.path.sep, os.path.altsep] if sep not in (None, "/") -) - - -def get_env(): - """Get the environment the app is running in, indicated by the - :envvar:`FLASK_ENV` environment variable. The default is - ``'production'``. - """ - return os.environ.get("FLASK_ENV") or "production" - - -def get_debug_flag(): - """Get whether debug mode should be enabled for the app, indicated - by the :envvar:`FLASK_DEBUG` environment variable. The default is - ``True`` if :func:`.get_env` returns ``'development'``, or ``False`` - otherwise. - """ - val = os.environ.get("FLASK_DEBUG") - - if not val: - return get_env() == "development" - - return val.lower() not in ("0", "false", "no") - - -def get_load_dotenv(default=True): - """Get whether the user has disabled loading dotenv files by setting - :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load the - files. - - :param default: What to return if the env var isn't set. - """ - val = os.environ.get("FLASK_SKIP_DOTENV") - - if not val: - return default - - return val.lower() in ("0", "false", "no") - - -def _endpoint_from_view_func(view_func): - """Internal helper that returns the default endpoint for a given - function. This always is the function name. - """ - assert view_func is not None, "expected view func if endpoint is not provided." - return view_func.__name__ - - -def stream_with_context(generator_or_function): - """Request contexts disappear when the response is started on the server. - This is done for efficiency reasons and to make it less likely to encounter - memory leaks with badly written WSGI middlewares. The downside is that if - you are using streamed responses, the generator cannot access request bound - information any more. - - This function however can help you keep the context around for longer:: - - from flask import stream_with_context, request, Response - - @app.route('/stream') - def streamed_response(): - @stream_with_context - def generate(): - yield 'Hello ' - yield request.args['name'] - yield '!' - return Response(generate()) - - Alternatively it can also be used around a specific generator:: - - from flask import stream_with_context, request, Response - - @app.route('/stream') - def streamed_response(): - def generate(): - yield 'Hello ' - yield request.args['name'] - yield '!' - return Response(stream_with_context(generate())) - - .. versionadded:: 0.9 - """ - try: - gen = iter(generator_or_function) - except TypeError: - - def decorator(*args, **kwargs): - gen = generator_or_function(*args, **kwargs) - return stream_with_context(gen) - - return update_wrapper(decorator, generator_or_function) - - def generator(): - ctx = _request_ctx_stack.top - if ctx is None: - raise RuntimeError( - "Attempted to stream with context but " - "there was no context in the first place to keep around." - ) - with ctx: - # Dummy sentinel. Has to be inside the context block or we're - # not actually keeping the context around. - yield None - - # The try/finally is here so that if someone passes a WSGI level - # iterator in we're still running the cleanup logic. Generators - # don't need that because they are closed on their destruction - # automatically. - try: - for item in gen: - yield item - finally: - if hasattr(gen, "close"): - gen.close() - - # The trick is to start the generator. Then the code execution runs until - # the first dummy None is yielded at which point the context was already - # pushed. This item is discarded. Then when the iteration continues the - # real generator is executed. - wrapped_g = generator() - next(wrapped_g) - return wrapped_g - - -def make_response(*args): - """Sometimes it is necessary to set additional headers in a view. Because - views do not have to return response objects but can return a value that - is converted into a response object by Flask itself, it becomes tricky to - add headers to it. This function can be called instead of using a return - and you will get a response object which you can use to attach headers. - - If view looked like this and you want to add a new header:: - - def index(): - return render_template('index.html', foo=42) - - You can now do something like this:: - - def index(): - response = make_response(render_template('index.html', foo=42)) - response.headers['X-Parachutes'] = 'parachutes are cool' - return response - - This function accepts the very same arguments you can return from a - view function. This for example creates a response with a 404 error - code:: - - response = make_response(render_template('not_found.html'), 404) - - The other use case of this function is to force the return value of a - view function into a response which is helpful with view - decorators:: - - response = make_response(view_function()) - response.headers['X-Parachutes'] = 'parachutes are cool' - - Internally this function does the following things: - - - if no arguments are passed, it creates a new response argument - - if one argument is passed, :meth:`flask.Flask.make_response` - is invoked with it. - - if more than one argument is passed, the arguments are passed - to the :meth:`flask.Flask.make_response` function as tuple. - - .. versionadded:: 0.6 - """ - if not args: - return current_app.response_class() - if len(args) == 1: - args = args[0] - return current_app.make_response(args) - - -def url_for(endpoint, **values): - """Generates a URL to the given endpoint with the method provided. - - Variable arguments that are unknown to the target endpoint are appended - to the generated URL as query arguments. If the value of a query argument - is ``None``, the whole pair is skipped. In case blueprints are active - you can shortcut references to the same blueprint by prefixing the - local endpoint with a dot (``.``). - - This will reference the index function local to the current blueprint:: - - url_for('.index') - - For more information, head over to the :ref:`Quickstart `. - - Configuration values ``APPLICATION_ROOT`` and ``SERVER_NAME`` are only used when - generating URLs outside of a request context. - - To integrate applications, :class:`Flask` has a hook to intercept URL build - errors through :attr:`Flask.url_build_error_handlers`. The `url_for` - function results in a :exc:`~werkzeug.routing.BuildError` when the current - app does not have a URL for the given endpoint and values. When it does, the - :data:`~flask.current_app` calls its :attr:`~Flask.url_build_error_handlers` if - it is not ``None``, which can return a string to use as the result of - `url_for` (instead of `url_for`'s default to raise the - :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception. - An example:: - - def external_url_handler(error, endpoint, values): - "Looks up an external URL when `url_for` cannot build a URL." - # This is an example of hooking the build_error_handler. - # Here, lookup_url is some utility function you've built - # which looks up the endpoint in some external URL registry. - url = lookup_url(endpoint, **values) - if url is None: - # External lookup did not have a URL. - # Re-raise the BuildError, in context of original traceback. - exc_type, exc_value, tb = sys.exc_info() - if exc_value is error: - raise exc_type, exc_value, tb - else: - raise error - # url_for will use this result, instead of raising BuildError. - return url - - app.url_build_error_handlers.append(external_url_handler) - - Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and - `endpoint` and `values` are the arguments passed into `url_for`. Note - that this is for building URLs outside the current application, and not for - handling 404 NotFound errors. - - .. versionadded:: 0.10 - The `_scheme` parameter was added. - - .. versionadded:: 0.9 - The `_anchor` and `_method` parameters were added. - - .. versionadded:: 0.9 - Calls :meth:`Flask.handle_build_error` on - :exc:`~werkzeug.routing.BuildError`. - - :param endpoint: the endpoint of the URL (name of the function) - :param values: the variable arguments of the URL rule - :param _external: if set to ``True``, an absolute URL is generated. Server - address can be changed via ``SERVER_NAME`` configuration variable which - falls back to the `Host` header, then to the IP and port of the request. - :param _scheme: a string specifying the desired URL scheme. The `_external` - parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default - behavior uses the same scheme as the current request, or - ``PREFERRED_URL_SCHEME`` from the :ref:`app configuration ` if no - request context is available. As of Werkzeug 0.10, this also can be set - to an empty string to build protocol-relative URLs. - :param _anchor: if provided this is added as anchor to the URL. - :param _method: if provided this explicitly specifies an HTTP method. - """ - appctx = _app_ctx_stack.top - reqctx = _request_ctx_stack.top - - if appctx is None: - raise RuntimeError( - "Attempted to generate a URL without the application context being" - " pushed. This has to be executed when application context is" - " available." - ) - - # If request specific information is available we have some extra - # features that support "relative" URLs. - if reqctx is not None: - url_adapter = reqctx.url_adapter - blueprint_name = request.blueprint - - if endpoint[:1] == ".": - if blueprint_name is not None: - endpoint = blueprint_name + endpoint - else: - endpoint = endpoint[1:] - - external = values.pop("_external", False) - - # Otherwise go with the url adapter from the appctx and make - # the URLs external by default. - else: - url_adapter = appctx.url_adapter - - if url_adapter is None: - raise RuntimeError( - "Application was not able to create a URL adapter for request" - " independent URL generation. You might be able to fix this by" - " setting the SERVER_NAME config variable." - ) - - external = values.pop("_external", True) - - anchor = values.pop("_anchor", None) - method = values.pop("_method", None) - scheme = values.pop("_scheme", None) - appctx.app.inject_url_defaults(endpoint, values) - - # This is not the best way to deal with this but currently the - # underlying Werkzeug router does not support overriding the scheme on - # a per build call basis. - old_scheme = None - if scheme is not None: - if not external: - raise ValueError("When specifying _scheme, _external must be True") - old_scheme = url_adapter.url_scheme - url_adapter.url_scheme = scheme - - try: - try: - rv = url_adapter.build( - endpoint, values, method=method, force_external=external - ) - finally: - if old_scheme is not None: - url_adapter.url_scheme = old_scheme - except BuildError as error: - # We need to inject the values again so that the app callback can - # deal with that sort of stuff. - values["_external"] = external - values["_anchor"] = anchor - values["_method"] = method - values["_scheme"] = scheme - return appctx.app.handle_url_build_error(error, endpoint, values) - - if anchor is not None: - rv += "#" + url_quote(anchor) - return rv - - -def get_template_attribute(template_name, attribute): - """Loads a macro (or variable) a template exports. This can be used to - invoke a macro from within Python code. If you for example have a - template named :file:`_cider.html` with the following contents: - - .. sourcecode:: html+jinja - - {% macro hello(name) %}Hello {{ name }}!{% endmacro %} - - You can access this from Python code like this:: - - hello = get_template_attribute('_cider.html', 'hello') - return hello('World') - - .. versionadded:: 0.2 - - :param template_name: the name of the template - :param attribute: the name of the variable of macro to access - """ - return getattr(current_app.jinja_env.get_template(template_name).module, attribute) - - -def flash(message, category="message"): - """Flashes a message to the next request. In order to remove the - flashed message from the session and to display it to the user, - the template has to call :func:`get_flashed_messages`. - - .. versionchanged:: 0.3 - `category` parameter added. - - :param message: the message to be flashed. - :param category: the category for the message. The following values - are recommended: ``'message'`` for any kind of message, - ``'error'`` for errors, ``'info'`` for information - messages and ``'warning'`` for warnings. However any - kind of string can be used as category. - """ - # Original implementation: - # - # session.setdefault('_flashes', []).append((category, message)) - # - # This assumed that changes made to mutable structures in the session are - # always in sync with the session object, which is not true for session - # implementations that use external storage for keeping their keys/values. - flashes = session.get("_flashes", []) - flashes.append((category, message)) - session["_flashes"] = flashes - message_flashed.send( - current_app._get_current_object(), message=message, category=category - ) - - -def get_flashed_messages(with_categories=False, category_filter=()): - """Pulls all flashed messages from the session and returns them. - Further calls in the same request to the function will return - the same messages. By default just the messages are returned, - but when `with_categories` is set to ``True``, the return value will - be a list of tuples in the form ``(category, message)`` instead. - - Filter the flashed messages to one or more categories by providing those - categories in `category_filter`. This allows rendering categories in - separate html blocks. The `with_categories` and `category_filter` - arguments are distinct: - - * `with_categories` controls whether categories are returned with message - text (``True`` gives a tuple, where ``False`` gives just the message text). - * `category_filter` filters the messages down to only those matching the - provided categories. - - See :ref:`message-flashing-pattern` for examples. - - .. versionchanged:: 0.3 - `with_categories` parameter added. - - .. versionchanged:: 0.9 - `category_filter` parameter added. - - :param with_categories: set to ``True`` to also receive categories. - :param category_filter: whitelist of categories to limit return values - """ - flashes = _request_ctx_stack.top.flashes - if flashes is None: - _request_ctx_stack.top.flashes = flashes = ( - session.pop("_flashes") if "_flashes" in session else [] - ) - if category_filter: - flashes = list(filter(lambda f: f[0] in category_filter, flashes)) - if not with_categories: - return [x[1] for x in flashes] - return flashes - - -def send_file( - filename_or_fp, - mimetype=None, - as_attachment=False, - attachment_filename=None, - add_etags=True, - cache_timeout=None, - conditional=False, - last_modified=None, -): - """Sends the contents of a file to the client. This will use the - most efficient method available and configured. By default it will - try to use the WSGI server's file_wrapper support. Alternatively - you can set the application's :attr:`~Flask.use_x_sendfile` attribute - to ``True`` to directly emit an ``X-Sendfile`` header. This however - requires support of the underlying webserver for ``X-Sendfile``. - - By default it will try to guess the mimetype for you, but you can - also explicitly provide one. For extra security you probably want - to send certain files as attachment (HTML for instance). The mimetype - guessing requires a `filename` or an `attachment_filename` to be - provided. - - ETags will also be attached automatically if a `filename` is provided. You - can turn this off by setting `add_etags=False`. - - If `conditional=True` and `filename` is provided, this method will try to - upgrade the response stream to support range requests. This will allow - the request to be answered with partial content response. - - Please never pass filenames to this function from user sources; - you should use :func:`send_from_directory` instead. - - .. versionadded:: 0.2 - - .. versionadded:: 0.5 - The `add_etags`, `cache_timeout` and `conditional` parameters were - added. The default behavior is now to attach etags. - - .. versionchanged:: 0.7 - mimetype guessing and etag support for file objects was - deprecated because it was unreliable. Pass a filename if you are - able to, otherwise attach an etag yourself. This functionality - will be removed in Flask 1.0 - - .. versionchanged:: 0.9 - cache_timeout pulls its default from application config, when None. - - .. versionchanged:: 0.12 - The filename is no longer automatically inferred from file objects. If - you want to use automatic mimetype and etag support, pass a filepath via - `filename_or_fp` or `attachment_filename`. - - .. versionchanged:: 0.12 - The `attachment_filename` is preferred over `filename` for MIME-type - detection. - - .. versionchanged:: 1.0 - UTF-8 filenames, as specified in `RFC 2231`_, are supported. - - .. _RFC 2231: https://tools.ietf.org/html/rfc2231#section-4 - - .. versionchanged:: 1.0.3 - Filenames are encoded with ASCII instead of Latin-1 for broader - compatibility with WSGI servers. - - .. versionchanged:: 1.1 - Filename may be a :class:`~os.PathLike` object. - - .. versionadded:: 1.1 - Partial content supports :class:`~io.BytesIO`. - - :param filename_or_fp: the filename of the file to send. - This is relative to the :attr:`~Flask.root_path` - if a relative path is specified. - Alternatively a file object might be provided in - which case ``X-Sendfile`` might not work and fall - back to the traditional method. Make sure that the - file pointer is positioned at the start of data to - send before calling :func:`send_file`. - :param mimetype: the mimetype of the file if provided. If a file path is - given, auto detection happens as fallback, otherwise an - error will be raised. - :param as_attachment: set to ``True`` if you want to send this file with - a ``Content-Disposition: attachment`` header. - :param attachment_filename: the filename for the attachment if it - differs from the file's filename. - :param add_etags: set to ``False`` to disable attaching of etags. - :param conditional: set to ``True`` to enable conditional responses. - - :param cache_timeout: the timeout in seconds for the headers. When ``None`` - (default), this value is set by - :meth:`~Flask.get_send_file_max_age` of - :data:`~flask.current_app`. - :param last_modified: set the ``Last-Modified`` header to this value, - a :class:`~datetime.datetime` or timestamp. - If a file was passed, this overrides its mtime. - """ - mtime = None - fsize = None - - if hasattr(filename_or_fp, "__fspath__"): - filename_or_fp = fspath(filename_or_fp) - - if isinstance(filename_or_fp, string_types): - filename = filename_or_fp - if not os.path.isabs(filename): - filename = os.path.join(current_app.root_path, filename) - file = None - if attachment_filename is None: - attachment_filename = os.path.basename(filename) - else: - file = filename_or_fp - filename = None - - if mimetype is None: - if attachment_filename is not None: - mimetype = ( - mimetypes.guess_type(attachment_filename)[0] - or "application/octet-stream" - ) - - if mimetype is None: - raise ValueError( - "Unable to infer MIME-type because no filename is available. " - "Please set either `attachment_filename`, pass a filepath to " - "`filename_or_fp` or set your own MIME-type via `mimetype`." - ) - - headers = Headers() - if as_attachment: - if attachment_filename is None: - raise TypeError("filename unavailable, required for sending as attachment") - - if not isinstance(attachment_filename, text_type): - attachment_filename = attachment_filename.decode("utf-8") - - try: - attachment_filename = attachment_filename.encode("ascii") - except UnicodeEncodeError: - filenames = { - "filename": unicodedata.normalize("NFKD", attachment_filename).encode( - "ascii", "ignore" - ), - "filename*": "UTF-8''%s" % url_quote(attachment_filename, safe=b""), - } - else: - filenames = {"filename": attachment_filename} - - headers.add("Content-Disposition", "attachment", **filenames) - - if current_app.use_x_sendfile and filename: - if file is not None: - file.close() - headers["X-Sendfile"] = filename - fsize = os.path.getsize(filename) - headers["Content-Length"] = fsize - data = None - else: - if file is None: - file = open(filename, "rb") - mtime = os.path.getmtime(filename) - fsize = os.path.getsize(filename) - headers["Content-Length"] = fsize - elif isinstance(file, io.BytesIO): - try: - fsize = file.getbuffer().nbytes - except AttributeError: - # Python 2 doesn't have getbuffer - fsize = len(file.getvalue()) - headers["Content-Length"] = fsize - data = wrap_file(request.environ, file) - - rv = current_app.response_class( - data, mimetype=mimetype, headers=headers, direct_passthrough=True - ) - - if last_modified is not None: - rv.last_modified = last_modified - elif mtime is not None: - rv.last_modified = mtime - - rv.cache_control.public = True - if cache_timeout is None: - cache_timeout = current_app.get_send_file_max_age(filename) - if cache_timeout is not None: - rv.cache_control.max_age = cache_timeout - rv.expires = int(time() + cache_timeout) - - if add_etags and filename is not None: - from warnings import warn - - try: - rv.set_etag( - "%s-%s-%s" - % ( - os.path.getmtime(filename), - os.path.getsize(filename), - adler32( - filename.encode("utf-8") - if isinstance(filename, text_type) - else filename - ) - & 0xFFFFFFFF, - ) - ) - except OSError: - warn( - "Access %s failed, maybe it does not exist, so ignore etags in " - "headers" % filename, - stacklevel=2, - ) - - if conditional: - try: - rv = rv.make_conditional(request, accept_ranges=True, complete_length=fsize) - except RequestedRangeNotSatisfiable: - if file is not None: - file.close() - raise - # make sure we don't send x-sendfile for servers that - # ignore the 304 status code for x-sendfile. - if rv.status_code == 304: - rv.headers.pop("x-sendfile", None) - return rv - - -def safe_join(directory, *pathnames): - """Safely join `directory` and zero or more untrusted `pathnames` - components. - - Example usage:: - - @app.route('/wiki/') - def wiki_page(filename): - filename = safe_join(app.config['WIKI_FOLDER'], filename) - with open(filename, 'rb') as fd: - content = fd.read() # Read and process the file content... - - :param directory: the trusted base directory. - :param pathnames: the untrusted pathnames relative to that directory. - :raises: :class:`~werkzeug.exceptions.NotFound` if one or more passed - paths fall out of its boundaries. - """ - - parts = [directory] - - for filename in pathnames: - if filename != "": - filename = posixpath.normpath(filename) - - if ( - any(sep in filename for sep in _os_alt_seps) - or os.path.isabs(filename) - or filename == ".." - or filename.startswith("../") - ): - raise NotFound() - - parts.append(filename) - - return posixpath.join(*parts) - - -def send_from_directory(directory, filename, **options): - """Send a file from a given directory with :func:`send_file`. This - is a secure way to quickly expose static files from an upload folder - or something similar. - - Example usage:: - - @app.route('/uploads/') - def download_file(filename): - return send_from_directory(app.config['UPLOAD_FOLDER'], - filename, as_attachment=True) - - .. admonition:: Sending files and Performance - - It is strongly recommended to activate either ``X-Sendfile`` support in - your webserver or (if no authentication happens) to tell the webserver - to serve files for the given path on its own without calling into the - web application for improved performance. - - .. versionadded:: 0.5 - - :param directory: the directory where all the files are stored. - :param filename: the filename relative to that directory to - download. - :param options: optional keyword arguments that are directly - forwarded to :func:`send_file`. - """ - filename = fspath(filename) - directory = fspath(directory) - filename = safe_join(directory, filename) - if not os.path.isabs(filename): - filename = os.path.join(current_app.root_path, filename) - try: - if not os.path.isfile(filename): - raise NotFound() - except (TypeError, ValueError): - raise BadRequest() - options.setdefault("conditional", True) - return send_file(filename, **options) - - -def get_root_path(import_name): - """Returns the path to a package or cwd if that cannot be found. This - returns the path of a package or the folder that contains a module. - - Not to be confused with the package path returned by :func:`find_package`. - """ - # Module already imported and has a file attribute. Use that first. - mod = sys.modules.get(import_name) - if mod is not None and hasattr(mod, "__file__"): - return os.path.dirname(os.path.abspath(mod.__file__)) - - # Next attempt: check the loader. - loader = pkgutil.get_loader(import_name) - - # Loader does not exist or we're referring to an unloaded main module - # or a main module without path (interactive sessions), go with the - # current working directory. - if loader is None or import_name == "__main__": - return os.getcwd() - - # For .egg, zipimporter does not have get_filename until Python 2.7. - # Some other loaders might exhibit the same behavior. - if hasattr(loader, "get_filename"): - filepath = loader.get_filename(import_name) - else: - # Fall back to imports. - __import__(import_name) - mod = sys.modules[import_name] - filepath = getattr(mod, "__file__", None) - - # If we don't have a filepath it might be because we are a - # namespace package. In this case we pick the root path from the - # first module that is contained in our package. - if filepath is None: - raise RuntimeError( - "No root path can be found for the provided " - 'module "%s". This can happen because the ' - "module came from an import hook that does " - "not provide file name information or because " - "it's a namespace package. In this case " - "the root path needs to be explicitly " - "provided." % import_name - ) - - # filepath is import_name.py for a module, or __init__.py for a package. - return os.path.dirname(os.path.abspath(filepath)) - - -def _matching_loader_thinks_module_is_package(loader, mod_name): - """Given the loader that loaded a module and the module this function - attempts to figure out if the given module is actually a package. - """ - # If the loader can tell us if something is a package, we can - # directly ask the loader. - if hasattr(loader, "is_package"): - return loader.is_package(mod_name) - # importlib's namespace loaders do not have this functionality but - # all the modules it loads are packages, so we can take advantage of - # this information. - elif ( - loader.__class__.__module__ == "_frozen_importlib" - and loader.__class__.__name__ == "NamespaceLoader" - ): - return True - # Otherwise we need to fail with an error that explains what went - # wrong. - raise AttributeError( - ( - "%s.is_package() method is missing but is required by Flask of " - "PEP 302 import hooks. If you do not use import hooks and " - "you encounter this error please file a bug against Flask." - ) - % loader.__class__.__name__ - ) - - -def _find_package_path(root_mod_name): - """Find the path where the module's root exists in""" - if sys.version_info >= (3, 4): - import importlib.util - - try: - spec = importlib.util.find_spec(root_mod_name) - if spec is None: - raise ValueError("not found") - # ImportError: the machinery told us it does not exist - # ValueError: - # - the module name was invalid - # - the module name is __main__ - # - *we* raised `ValueError` due to `spec` being `None` - except (ImportError, ValueError): - pass # handled below - else: - # namespace package - if spec.origin in {"namespace", None}: - return os.path.dirname(next(iter(spec.submodule_search_locations))) - # a package (with __init__.py) - elif spec.submodule_search_locations: - return os.path.dirname(os.path.dirname(spec.origin)) - # just a normal module - else: - return os.path.dirname(spec.origin) - - # we were unable to find the `package_path` using PEP 451 loaders - loader = pkgutil.get_loader(root_mod_name) - if loader is None or root_mod_name == "__main__": - # import name is not found, or interactive/main module - return os.getcwd() - else: - # For .egg, zipimporter does not have get_filename until Python 2.7. - if hasattr(loader, "get_filename"): - filename = loader.get_filename(root_mod_name) - elif hasattr(loader, "archive"): - # zipimporter's loader.archive points to the .egg or .zip - # archive filename is dropped in call to dirname below. - filename = loader.archive - else: - # At least one loader is missing both get_filename and archive: - # Google App Engine's HardenedModulesHook - # - # Fall back to imports. - __import__(root_mod_name) - filename = sys.modules[root_mod_name].__file__ - package_path = os.path.abspath(os.path.dirname(filename)) - - # In case the root module is a package we need to chop of the - # rightmost part. This needs to go through a helper function - # because of python 3.3 namespace packages. - if _matching_loader_thinks_module_is_package(loader, root_mod_name): - package_path = os.path.dirname(package_path) - - return package_path - - -def find_package(import_name): - """Finds a package and returns the prefix (or None if the package is - not installed) as well as the folder that contains the package or - module as a tuple. The package path returned is the module that would - have to be added to the pythonpath in order to make it possible to - import the module. The prefix is the path below which a UNIX like - folder structure exists (lib, share etc.). - """ - root_mod_name, _, _ = import_name.partition(".") - package_path = _find_package_path(root_mod_name) - site_parent, site_folder = os.path.split(package_path) - py_prefix = os.path.abspath(sys.prefix) - if package_path.startswith(py_prefix): - return py_prefix, package_path - elif site_folder.lower() == "site-packages": - parent, folder = os.path.split(site_parent) - # Windows like installations - if folder.lower() == "lib": - base_dir = parent - # UNIX like installations - elif os.path.basename(parent).lower() == "lib": - base_dir = os.path.dirname(parent) - else: - base_dir = site_parent - return base_dir, package_path - return None, package_path - - -class locked_cached_property(object): - """A decorator that converts a function into a lazy property. The - function wrapped is called the first time to retrieve the result - and then that calculated result is used the next time you access - the value. Works like the one in Werkzeug but has a lock for - thread safety. - """ - - def __init__(self, func, name=None, doc=None): - self.__name__ = name or func.__name__ - self.__module__ = func.__module__ - self.__doc__ = doc or func.__doc__ - self.func = func - self.lock = RLock() - - def __get__(self, obj, type=None): - if obj is None: - return self - with self.lock: - value = obj.__dict__.get(self.__name__, _missing) - if value is _missing: - value = self.func(obj) - obj.__dict__[self.__name__] = value - return value - - -class _PackageBoundObject(object): - #: The name of the package or module that this app belongs to. Do not - #: change this once it is set by the constructor. - import_name = None - - #: Location of the template files to be added to the template lookup. - #: ``None`` if templates should not be added. - template_folder = None - - #: Absolute path to the package on the filesystem. Used to look up - #: resources contained in the package. - root_path = None - - def __init__(self, import_name, template_folder=None, root_path=None): - self.import_name = import_name - self.template_folder = template_folder - - if root_path is None: - root_path = get_root_path(self.import_name) - - self.root_path = root_path - self._static_folder = None - self._static_url_path = None - - # circular import - from .cli import AppGroup - - #: The Click command group for registration of CLI commands - #: on the application and associated blueprints. These commands - #: are accessible via the :command:`flask` command once the - #: application has been discovered and blueprints registered. - self.cli = AppGroup() - - @property - def static_folder(self): - """The absolute path to the configured static folder.""" - if self._static_folder is not None: - return os.path.join(self.root_path, self._static_folder) - - @static_folder.setter - def static_folder(self, value): - if value is not None: - value = value.rstrip("/\\") - self._static_folder = value - - @property - def static_url_path(self): - """The URL prefix that the static route will be accessible from. - - If it was not configured during init, it is derived from - :attr:`static_folder`. - """ - if self._static_url_path is not None: - return self._static_url_path - - if self.static_folder is not None: - basename = os.path.basename(self.static_folder) - return ("/" + basename).rstrip("/") - - @static_url_path.setter - def static_url_path(self, value): - if value is not None: - value = value.rstrip("/") - - self._static_url_path = value - - @property - def has_static_folder(self): - """This is ``True`` if the package bound object's container has a - folder for static files. - - .. versionadded:: 0.5 - """ - return self.static_folder is not None - - @locked_cached_property - def jinja_loader(self): - """The Jinja loader for this package bound object. - - .. versionadded:: 0.5 - """ - if self.template_folder is not None: - return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) - - def get_send_file_max_age(self, filename): - """Provides default cache_timeout for the :func:`send_file` functions. - - By default, this function returns ``SEND_FILE_MAX_AGE_DEFAULT`` from - the configuration of :data:`~flask.current_app`. - - Static file functions such as :func:`send_from_directory` use this - function, and :func:`send_file` calls this function on - :data:`~flask.current_app` when the given cache_timeout is ``None``. If a - cache_timeout is given in :func:`send_file`, that timeout is used; - otherwise, this method is called. - - This allows subclasses to change the behavior when sending files based - on the filename. For example, to set the cache timeout for .js files - to 60 seconds:: - - class MyFlask(flask.Flask): - def get_send_file_max_age(self, name): - if name.lower().endswith('.js'): - return 60 - return flask.Flask.get_send_file_max_age(self, name) - - .. versionadded:: 0.9 - """ - return total_seconds(current_app.send_file_max_age_default) - - def send_static_file(self, filename): - """Function used internally to send static files from the static - folder to the browser. - - .. versionadded:: 0.5 - """ - if not self.has_static_folder: - raise RuntimeError("No static folder for this object") - # Ensure get_send_file_max_age is called in all cases. - # Here, we ensure get_send_file_max_age is called for Blueprints. - cache_timeout = self.get_send_file_max_age(filename) - return send_from_directory( - self.static_folder, filename, cache_timeout=cache_timeout - ) - - def open_resource(self, resource, mode="rb"): - """Opens a resource from the application's resource folder. To see - how this works, consider the following folder structure:: - - /myapplication.py - /schema.sql - /static - /style.css - /templates - /layout.html - /index.html - - If you want to open the :file:`schema.sql` file you would do the - following:: - - with app.open_resource('schema.sql') as f: - contents = f.read() - do_something_with(contents) - - :param resource: the name of the resource. To access resources within - subfolders use forward slashes as separator. - :param mode: Open file in this mode. Only reading is supported, - valid values are "r" (or "rt") and "rb". - """ - if mode not in {"r", "rt", "rb"}: - raise ValueError("Resources can only be opened for reading") - - return open(os.path.join(self.root_path, resource), mode) - - -def total_seconds(td): - """Returns the total seconds from a timedelta object. - - :param timedelta td: the timedelta to be converted in seconds - - :returns: number of seconds - :rtype: int - """ - return td.days * 60 * 60 * 24 + td.seconds - - -def is_ip(value): - """Determine if the given string is an IP address. - - Python 2 on Windows doesn't provide ``inet_pton``, so this only - checks IPv4 addresses in that environment. - - :param value: value to check - :type value: str - - :return: True if string is an IP address - :rtype: bool - """ - if PY2 and os.name == "nt": - try: - socket.inet_aton(value) - return True - except socket.error: - return False - - for family in (socket.AF_INET, socket.AF_INET6): - try: - socket.inet_pton(family, value) - except socket.error: - pass - else: - return True - - return False diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__init__.py deleted file mode 100644 index a141068..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/flask/json/__init__.py +++ /dev/null @@ -1,376 +0,0 @@ -# -*- coding: utf-8 -*- -""" -flask.json -~~~~~~~~~~ - -:copyright: 2010 Pallets -:license: BSD-3-Clause -""" -import codecs -import io -import uuid -from datetime import date -from datetime import datetime - -from itsdangerous import json as _json -from jinja2 import Markup -from werkzeug.http import http_date - -from .._compat import PY2 -from .._compat import text_type -from ..globals import current_app -from ..globals import request - -try: - import dataclasses -except ImportError: - dataclasses = None - -# Figure out if simplejson escapes slashes. This behavior was changed -# from one version to another without reason. -_slash_escape = "\\/" not in _json.dumps("/") - - -__all__ = [ - "dump", - "dumps", - "load", - "loads", - "htmlsafe_dump", - "htmlsafe_dumps", - "JSONDecoder", - "JSONEncoder", - "jsonify", -] - - -def _wrap_reader_for_text(fp, encoding): - if isinstance(fp.read(0), bytes): - fp = io.TextIOWrapper(io.BufferedReader(fp), encoding) - return fp - - -def _wrap_writer_for_text(fp, encoding): - try: - fp.write("") - except TypeError: - fp = io.TextIOWrapper(fp, encoding) - return fp - - -class JSONEncoder(_json.JSONEncoder): - """The default Flask JSON encoder. This one extends the default - encoder by also supporting ``datetime``, ``UUID``, ``dataclasses``, - and ``Markup`` objects. - - ``datetime`` objects are serialized as RFC 822 datetime strings. - This is the same as the HTTP date format. - - In order to support more data types, override the :meth:`default` - method. - """ - - def default(self, o): - """Implement this method in a subclass such that it returns a - serializable object for ``o``, or calls the base implementation (to - raise a :exc:`TypeError`). - - For example, to support arbitrary iterators, you could implement - default like this:: - - def default(self, o): - try: - iterable = iter(o) - except TypeError: - pass - else: - return list(iterable) - return JSONEncoder.default(self, o) - """ - if isinstance(o, datetime): - return http_date(o.utctimetuple()) - if isinstance(o, date): - return http_date(o.timetuple()) - if isinstance(o, uuid.UUID): - return str(o) - if dataclasses and dataclasses.is_dataclass(o): - return dataclasses.asdict(o) - if hasattr(o, "__html__"): - return text_type(o.__html__()) - return _json.JSONEncoder.default(self, o) - - -class JSONDecoder(_json.JSONDecoder): - """The default JSON decoder. This one does not change the behavior from - the default simplejson decoder. Consult the :mod:`json` documentation - for more information. This decoder is not only used for the load - functions of this module but also :attr:`~flask.Request`. - """ - - -def _dump_arg_defaults(kwargs, app=None): - """Inject default arguments for dump functions.""" - if app is None: - app = current_app - - if app: - bp = app.blueprints.get(request.blueprint) if request else None - kwargs.setdefault( - "cls", bp.json_encoder if bp and bp.json_encoder else app.json_encoder - ) - - if not app.config["JSON_AS_ASCII"]: - kwargs.setdefault("ensure_ascii", False) - - kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"]) - else: - kwargs.setdefault("sort_keys", True) - kwargs.setdefault("cls", JSONEncoder) - - -def _load_arg_defaults(kwargs, app=None): - """Inject default arguments for load functions.""" - if app is None: - app = current_app - - if app: - bp = app.blueprints.get(request.blueprint) if request else None - kwargs.setdefault( - "cls", bp.json_decoder if bp and bp.json_decoder else app.json_decoder - ) - else: - kwargs.setdefault("cls", JSONDecoder) - - -def detect_encoding(data): - """Detect which UTF codec was used to encode the given bytes. - - The latest JSON standard (:rfc:`8259`) suggests that only UTF-8 is - accepted. Older documents allowed 8, 16, or 32. 16 and 32 can be big - or little endian. Some editors or libraries may prepend a BOM. - - :param data: Bytes in unknown UTF encoding. - :return: UTF encoding name - """ - head = data[:4] - - if head[:3] == codecs.BOM_UTF8: - return "utf-8-sig" - - if b"\x00" not in head: - return "utf-8" - - if head in (codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE): - return "utf-32" - - if head[:2] in (codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE): - return "utf-16" - - if len(head) == 4: - if head[:3] == b"\x00\x00\x00": - return "utf-32-be" - - if head[::2] == b"\x00\x00": - return "utf-16-be" - - if head[1:] == b"\x00\x00\x00": - return "utf-32-le" - - if head[1::2] == b"\x00\x00": - return "utf-16-le" - - if len(head) == 2: - return "utf-16-be" if head.startswith(b"\x00") else "utf-16-le" - - return "utf-8" - - -def dumps(obj, app=None, **kwargs): - """Serialize ``obj`` to a JSON-formatted string. If there is an - app context pushed, use the current app's configured encoder - (:attr:`~flask.Flask.json_encoder`), or fall back to the default - :class:`JSONEncoder`. - - Takes the same arguments as the built-in :func:`json.dumps`, and - does some extra configuration based on the application. If the - simplejson package is installed, it is preferred. - - :param obj: Object to serialize to JSON. - :param app: App instance to use to configure the JSON encoder. - Uses ``current_app`` if not given, and falls back to the default - encoder when not in an app context. - :param kwargs: Extra arguments passed to :func:`json.dumps`. - - .. versionchanged:: 1.0.3 - - ``app`` can be passed directly, rather than requiring an app - context for configuration. - """ - _dump_arg_defaults(kwargs, app=app) - encoding = kwargs.pop("encoding", None) - rv = _json.dumps(obj, **kwargs) - if encoding is not None and isinstance(rv, text_type): - rv = rv.encode(encoding) - return rv - - -def dump(obj, fp, app=None, **kwargs): - """Like :func:`dumps` but writes into a file object.""" - _dump_arg_defaults(kwargs, app=app) - encoding = kwargs.pop("encoding", None) - if encoding is not None: - fp = _wrap_writer_for_text(fp, encoding) - _json.dump(obj, fp, **kwargs) - - -def loads(s, app=None, **kwargs): - """Deserialize an object from a JSON-formatted string ``s``. If - there is an app context pushed, use the current app's configured - decoder (:attr:`~flask.Flask.json_decoder`), or fall back to the - default :class:`JSONDecoder`. - - Takes the same arguments as the built-in :func:`json.loads`, and - does some extra configuration based on the application. If the - simplejson package is installed, it is preferred. - - :param s: JSON string to deserialize. - :param app: App instance to use to configure the JSON decoder. - Uses ``current_app`` if not given, and falls back to the default - encoder when not in an app context. - :param kwargs: Extra arguments passed to :func:`json.dumps`. - - .. versionchanged:: 1.0.3 - - ``app`` can be passed directly, rather than requiring an app - context for configuration. - """ - _load_arg_defaults(kwargs, app=app) - if isinstance(s, bytes): - encoding = kwargs.pop("encoding", None) - if encoding is None: - encoding = detect_encoding(s) - s = s.decode(encoding) - return _json.loads(s, **kwargs) - - -def load(fp, app=None, **kwargs): - """Like :func:`loads` but reads from a file object.""" - _load_arg_defaults(kwargs, app=app) - if not PY2: - fp = _wrap_reader_for_text(fp, kwargs.pop("encoding", None) or "utf-8") - return _json.load(fp, **kwargs) - - -def htmlsafe_dumps(obj, **kwargs): - """Works exactly like :func:`dumps` but is safe for use in ``') - # => <script> do_nasty_stuff() </script> - # sanitize_html('Click here for $100') - # => Click here for $100 - def sanitize_token(self, token): - - # accommodate filters which use token_type differently - token_type = token["type"] - if token_type in ("StartTag", "EndTag", "EmptyTag"): - name = token["name"] - namespace = token["namespace"] - if ((namespace, name) in self.allowed_elements or - (namespace is None and - (namespaces["html"], name) in self.allowed_elements)): - return self.allowed_token(token) - else: - return self.disallowed_token(token) - elif token_type == "Comment": - pass - else: - return token - - def allowed_token(self, token): - if "data" in token: - attrs = token["data"] - attr_names = set(attrs.keys()) - - # Remove forbidden attributes - for to_remove in (attr_names - self.allowed_attributes): - del token["data"][to_remove] - attr_names.remove(to_remove) - - # Remove attributes with disallowed URL values - for attr in (attr_names & self.attr_val_is_uri): - assert attr in attrs - # I don't have a clue where this regexp comes from or why it matches those - # characters, nor why we call unescape. I just know it's always been here. - # Should you be worried by this comment in a sanitizer? Yes. On the other hand, all - # this will do is remove *more* than it otherwise would. - val_unescaped = re.sub("[`\x00-\x20\x7f-\xa0\\s]+", '', - unescape(attrs[attr])).lower() - # remove replacement characters from unescaped characters - val_unescaped = val_unescaped.replace("\ufffd", "") - try: - uri = urlparse.urlparse(val_unescaped) - except ValueError: - uri = None - del attrs[attr] - if uri and uri.scheme: - if uri.scheme not in self.allowed_protocols: - del attrs[attr] - if uri.scheme == 'data': - m = data_content_type.match(uri.path) - if not m: - del attrs[attr] - elif m.group('content_type') not in self.allowed_content_types: - del attrs[attr] - - for attr in self.svg_attr_val_allows_ref: - if attr in attrs: - attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)', - ' ', - unescape(attrs[attr])) - if (token["name"] in self.svg_allow_local_href and - (namespaces['xlink'], 'href') in attrs and re.search(r'^\s*[^#\s].*', - attrs[(namespaces['xlink'], 'href')])): - del attrs[(namespaces['xlink'], 'href')] - if (None, 'style') in attrs: - attrs[(None, 'style')] = self.sanitize_css(attrs[(None, 'style')]) - token["data"] = attrs - return token - - def disallowed_token(self, token): - token_type = token["type"] - if token_type == "EndTag": - token["data"] = "" % token["name"] - elif token["data"]: - assert token_type in ("StartTag", "EmptyTag") - attrs = [] - for (ns, name), v in token["data"].items(): - attrs.append(' %s="%s"' % (name if ns is None else "%s:%s" % (prefixes[ns], name), escape(v))) - token["data"] = "<%s%s>" % (token["name"], ''.join(attrs)) - else: - token["data"] = "<%s>" % token["name"] - if token.get("selfClosing"): - token["data"] = token["data"][:-1] + "/>" - - token["type"] = "Characters" - - del token["name"] - return token - - def sanitize_css(self, style): - # disallow urls - style = re.compile(r'url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) - - # gauntlet - if not re.match(r"""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): - return '' - if not re.match(r"^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): - return '' - - clean = [] - for prop, value in re.findall(r"([-\w]+)\s*:\s*([^:;]*)", style): - if not value: - continue - if prop.lower() in self.allowed_css_properties: - clean.append(prop + ': ' + value + ';') - elif prop.split('-')[0].lower() in ['background', 'border', 'margin', - 'padding']: - for keyword in value.split(): - if keyword not in self.allowed_css_keywords and \ - not re.match(r"^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): # noqa - break - else: - clean.append(prop + ': ' + value + ';') - elif prop.lower() in self.allowed_svg_properties: - clean.append(prop + ': ' + value + ';') - - return ' '.join(clean) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py deleted file mode 100644 index 0d12584..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import re - -from . import base -from ..constants import rcdataElements, spaceCharacters -spaceCharacters = "".join(spaceCharacters) - -SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) - - -class Filter(base.Filter): - """Collapses whitespace except in pre, textarea, and script elements""" - spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) - - def __iter__(self): - preserve = 0 - for token in base.Filter.__iter__(self): - type = token["type"] - if type == "StartTag" \ - and (preserve or token["name"] in self.spacePreserveElements): - preserve += 1 - - elif type == "EndTag" and preserve: - preserve -= 1 - - elif not preserve and type == "SpaceCharacters" and token["data"]: - # Test on token["data"] above to not introduce spaces where there were not - token["data"] = " " - - elif not preserve and type == "Characters": - token["data"] = collapse_spaces(token["data"]) - - yield token - - -def collapse_spaces(text): - return SPACES_REGEX.sub(' ', text) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py deleted file mode 100644 index ae41a13..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py +++ /dev/null @@ -1,2791 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import with_metaclass, viewkeys - -import types -from collections import OrderedDict - -from . import _inputstream -from . import _tokenizer - -from . import treebuilders -from .treebuilders.base import Marker - -from . import _utils -from .constants import ( - spaceCharacters, asciiUpper2Lower, - specialElements, headingElements, cdataElements, rcdataElements, - tokenTypes, tagTokenTypes, - namespaces, - htmlIntegrationPointElements, mathmlTextIntegrationPointElements, - adjustForeignAttributes as adjustForeignAttributesMap, - adjustMathMLAttributes, adjustSVGAttributes, - E, - _ReparseException -) - - -def parse(doc, treebuilder="etree", namespaceHTMLElements=True, **kwargs): - """Parse an HTML document as a string or file-like object into a tree - - :arg doc: the document to parse as a string or file-like object - - :arg treebuilder: the treebuilder to use when parsing - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :returns: parsed tree - - Example: - - >>> from html5lib.html5parser import parse - >>> parse('

This is a doc

') - - - """ - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parse(doc, **kwargs) - - -def parseFragment(doc, container="div", treebuilder="etree", namespaceHTMLElements=True, **kwargs): - """Parse an HTML fragment as a string or file-like object into a tree - - :arg doc: the fragment to parse as a string or file-like object - - :arg container: the container context to parse the fragment in - - :arg treebuilder: the treebuilder to use when parsing - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :returns: parsed tree - - Example: - - >>> from html5lib.html5libparser import parseFragment - >>> parseFragment('this is a fragment') - - - """ - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parseFragment(doc, container=container, **kwargs) - - -def method_decorator_metaclass(function): - class Decorated(type): - def __new__(meta, classname, bases, classDict): - for attributeName, attribute in classDict.items(): - if isinstance(attribute, types.FunctionType): - attribute = function(attribute) - - classDict[attributeName] = attribute - return type.__new__(meta, classname, bases, classDict) - return Decorated - - -class HTMLParser(object): - """HTML parser - - Generates a tree structure from a stream of (possibly malformed) HTML. - - """ - - def __init__(self, tree=None, strict=False, namespaceHTMLElements=True, debug=False): - """ - :arg tree: a treebuilder class controlling the type of tree that will be - returned. Built in treebuilders can be accessed through - html5lib.treebuilders.getTreeBuilder(treeType) - - :arg strict: raise an exception when a parse error is encountered - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :arg debug: whether or not to enable debug mode which logs things - - Example: - - >>> from html5lib.html5parser import HTMLParser - >>> parser = HTMLParser() # generates parser with etree builder - >>> parser = HTMLParser('lxml', strict=True) # generates parser with lxml builder which is strict - - """ - - # Raise an exception on the first error encountered - self.strict = strict - - if tree is None: - tree = treebuilders.getTreeBuilder("etree") - self.tree = tree(namespaceHTMLElements) - self.errors = [] - - self.phases = dict([(name, cls(self, self.tree)) for name, cls in - getPhases(debug).items()]) - - def _parse(self, stream, innerHTML=False, container="div", scripting=False, **kwargs): - - self.innerHTMLMode = innerHTML - self.container = container - self.scripting = scripting - self.tokenizer = _tokenizer.HTMLTokenizer(stream, parser=self, **kwargs) - self.reset() - - try: - self.mainLoop() - except _ReparseException: - self.reset() - self.mainLoop() - - def reset(self): - self.tree.reset() - self.firstStartTag = False - self.errors = [] - self.log = [] # only used with debug mode - # "quirks" / "limited quirks" / "no quirks" - self.compatMode = "no quirks" - - if self.innerHTMLMode: - self.innerHTML = self.container.lower() - - if self.innerHTML in cdataElements: - self.tokenizer.state = self.tokenizer.rcdataState - elif self.innerHTML in rcdataElements: - self.tokenizer.state = self.tokenizer.rawtextState - elif self.innerHTML == 'plaintext': - self.tokenizer.state = self.tokenizer.plaintextState - else: - # state already is data state - # self.tokenizer.state = self.tokenizer.dataState - pass - self.phase = self.phases["beforeHtml"] - self.phase.insertHtmlElement() - self.resetInsertionMode() - else: - self.innerHTML = False # pylint:disable=redefined-variable-type - self.phase = self.phases["initial"] - - self.lastPhase = None - - self.beforeRCDataPhase = None - - self.framesetOK = True - - @property - def documentEncoding(self): - """Name of the character encoding that was used to decode the input stream, or - :obj:`None` if that is not determined yet - - """ - if not hasattr(self, 'tokenizer'): - return None - return self.tokenizer.stream.charEncoding[0].name - - def isHTMLIntegrationPoint(self, element): - if (element.name == "annotation-xml" and - element.namespace == namespaces["mathml"]): - return ("encoding" in element.attributes and - element.attributes["encoding"].translate( - asciiUpper2Lower) in - ("text/html", "application/xhtml+xml")) - else: - return (element.namespace, element.name) in htmlIntegrationPointElements - - def isMathMLTextIntegrationPoint(self, element): - return (element.namespace, element.name) in mathmlTextIntegrationPointElements - - def mainLoop(self): - CharactersToken = tokenTypes["Characters"] - SpaceCharactersToken = tokenTypes["SpaceCharacters"] - StartTagToken = tokenTypes["StartTag"] - EndTagToken = tokenTypes["EndTag"] - CommentToken = tokenTypes["Comment"] - DoctypeToken = tokenTypes["Doctype"] - ParseErrorToken = tokenTypes["ParseError"] - - for token in self.normalizedTokens(): - prev_token = None - new_token = token - while new_token is not None: - prev_token = new_token - currentNode = self.tree.openElements[-1] if self.tree.openElements else None - currentNodeNamespace = currentNode.namespace if currentNode else None - currentNodeName = currentNode.name if currentNode else None - - type = new_token["type"] - - if type == ParseErrorToken: - self.parseError(new_token["data"], new_token.get("datavars", {})) - new_token = None - else: - if (len(self.tree.openElements) == 0 or - currentNodeNamespace == self.tree.defaultNamespace or - (self.isMathMLTextIntegrationPoint(currentNode) and - ((type == StartTagToken and - token["name"] not in frozenset(["mglyph", "malignmark"])) or - type in (CharactersToken, SpaceCharactersToken))) or - (currentNodeNamespace == namespaces["mathml"] and - currentNodeName == "annotation-xml" and - type == StartTagToken and - token["name"] == "svg") or - (self.isHTMLIntegrationPoint(currentNode) and - type in (StartTagToken, CharactersToken, SpaceCharactersToken))): - phase = self.phase - else: - phase = self.phases["inForeignContent"] - - if type == CharactersToken: - new_token = phase.processCharacters(new_token) - elif type == SpaceCharactersToken: - new_token = phase.processSpaceCharacters(new_token) - elif type == StartTagToken: - new_token = phase.processStartTag(new_token) - elif type == EndTagToken: - new_token = phase.processEndTag(new_token) - elif type == CommentToken: - new_token = phase.processComment(new_token) - elif type == DoctypeToken: - new_token = phase.processDoctype(new_token) - - if (type == StartTagToken and prev_token["selfClosing"] and - not prev_token["selfClosingAcknowledged"]): - self.parseError("non-void-element-with-trailing-solidus", - {"name": prev_token["name"]}) - - # When the loop finishes it's EOF - reprocess = True - phases = [] - while reprocess: - phases.append(self.phase) - reprocess = self.phase.processEOF() - if reprocess: - assert self.phase not in phases - - def normalizedTokens(self): - for token in self.tokenizer: - yield self.normalizeToken(token) - - def parse(self, stream, *args, **kwargs): - """Parse a HTML document into a well-formed tree - - :arg stream: a file-like object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element). - - :arg scripting: treat noscript elements as if JavaScript was turned on - - :returns: parsed tree - - Example: - - >>> from html5lib.html5parser import HTMLParser - >>> parser = HTMLParser() - >>> parser.parse('

This is a doc

') - - - """ - self._parse(stream, False, None, *args, **kwargs) - return self.tree.getDocument() - - def parseFragment(self, stream, *args, **kwargs): - """Parse a HTML fragment into a well-formed tree fragment - - :arg container: name of the element we're setting the innerHTML - property if set to None, default to 'div' - - :arg stream: a file-like object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - - :arg scripting: treat noscript elements as if JavaScript was turned on - - :returns: parsed tree - - Example: - - >>> from html5lib.html5libparser import HTMLParser - >>> parser = HTMLParser() - >>> parser.parseFragment('this is a fragment') - - - """ - self._parse(stream, True, *args, **kwargs) - return self.tree.getFragment() - - def parseError(self, errorcode="XXX-undefined-error", datavars=None): - # XXX The idea is to make errorcode mandatory. - if datavars is None: - datavars = {} - self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) - if self.strict: - raise ParseError(E[errorcode] % datavars) - - def normalizeToken(self, token): - # HTML5 specific normalizations to the token stream - if token["type"] == tokenTypes["StartTag"]: - raw = token["data"] - token["data"] = OrderedDict(raw) - if len(raw) > len(token["data"]): - # we had some duplicated attribute, fix so first wins - token["data"].update(raw[::-1]) - - return token - - def adjustMathMLAttributes(self, token): - adjust_attributes(token, adjustMathMLAttributes) - - def adjustSVGAttributes(self, token): - adjust_attributes(token, adjustSVGAttributes) - - def adjustForeignAttributes(self, token): - adjust_attributes(token, adjustForeignAttributesMap) - - def reparseTokenNormal(self, token): - # pylint:disable=unused-argument - self.parser.phase() - - def resetInsertionMode(self): - # The name of this method is mostly historical. (It's also used in the - # specification.) - last = False - newModes = { - "select": "inSelect", - "td": "inCell", - "th": "inCell", - "tr": "inRow", - "tbody": "inTableBody", - "thead": "inTableBody", - "tfoot": "inTableBody", - "caption": "inCaption", - "colgroup": "inColumnGroup", - "table": "inTable", - "head": "inBody", - "body": "inBody", - "frameset": "inFrameset", - "html": "beforeHead" - } - for node in self.tree.openElements[::-1]: - nodeName = node.name - new_phase = None - if node == self.tree.openElements[0]: - assert self.innerHTML - last = True - nodeName = self.innerHTML - # Check for conditions that should only happen in the innerHTML - # case - if nodeName in ("select", "colgroup", "head", "html"): - assert self.innerHTML - - if not last and node.namespace != self.tree.defaultNamespace: - continue - - if nodeName in newModes: - new_phase = self.phases[newModes[nodeName]] - break - elif last: - new_phase = self.phases["inBody"] - break - - self.phase = new_phase - - def parseRCDataRawtext(self, token, contentType): - # Generic RCDATA/RAWTEXT Parsing algorithm - assert contentType in ("RAWTEXT", "RCDATA") - - self.tree.insertElement(token) - - if contentType == "RAWTEXT": - self.tokenizer.state = self.tokenizer.rawtextState - else: - self.tokenizer.state = self.tokenizer.rcdataState - - self.originalPhase = self.phase - - self.phase = self.phases["text"] - - -@_utils.memoize -def getPhases(debug): - def log(function): - """Logger that records which phase processes each token""" - type_names = dict((value, key) for key, value in - tokenTypes.items()) - - def wrapped(self, *args, **kwargs): - if function.__name__.startswith("process") and len(args) > 0: - token = args[0] - try: - info = {"type": type_names[token['type']]} - except: - raise - if token['type'] in tagTokenTypes: - info["name"] = token['name'] - - self.parser.log.append((self.parser.tokenizer.state.__name__, - self.parser.phase.__class__.__name__, - self.__class__.__name__, - function.__name__, - info)) - return function(self, *args, **kwargs) - else: - return function(self, *args, **kwargs) - return wrapped - - def getMetaclass(use_metaclass, metaclass_func): - if use_metaclass: - return method_decorator_metaclass(metaclass_func) - else: - return type - - # pylint:disable=unused-argument - class Phase(with_metaclass(getMetaclass(debug, log))): - """Base class for helper object that implements each phase of processing - """ - - def __init__(self, parser, tree): - self.parser = parser - self.tree = tree - - def processEOF(self): - raise NotImplementedError - - def processComment(self, token): - # For most phases the following is correct. Where it's not it will be - # overridden. - self.tree.insertComment(token, self.tree.openElements[-1]) - - def processDoctype(self, token): - self.parser.parseError("unexpected-doctype") - - def processCharacters(self, token): - self.tree.insertText(token["data"]) - - def processSpaceCharacters(self, token): - self.tree.insertText(token["data"]) - - def processStartTag(self, token): - return self.startTagHandler[token["name"]](token) - - def startTagHtml(self, token): - if not self.parser.firstStartTag and token["name"] == "html": - self.parser.parseError("non-html-root") - # XXX Need a check here to see if the first start tag token emitted is - # this token... If it's not, invoke self.parser.parseError(). - for attr, value in token["data"].items(): - if attr not in self.tree.openElements[0].attributes: - self.tree.openElements[0].attributes[attr] = value - self.parser.firstStartTag = False - - def processEndTag(self, token): - return self.endTagHandler[token["name"]](token) - - class InitialPhase(Phase): - def processSpaceCharacters(self, token): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processDoctype(self, token): - name = token["name"] - publicId = token["publicId"] - systemId = token["systemId"] - correct = token["correct"] - - if (name != "html" or publicId is not None or - systemId is not None and systemId != "about:legacy-compat"): - self.parser.parseError("unknown-doctype") - - if publicId is None: - publicId = "" - - self.tree.insertDoctype(token) - - if publicId != "": - publicId = publicId.translate(asciiUpper2Lower) - - if (not correct or token["name"] != "html" or - publicId.startswith( - ("+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//")) or - publicId in ("-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html") or - publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is None or - systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): - self.parser.compatMode = "quirks" - elif (publicId.startswith( - ("-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//")) or - publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is not None): - self.parser.compatMode = "limited quirks" - - self.parser.phase = self.parser.phases["beforeHtml"] - - def anythingElse(self): - self.parser.compatMode = "quirks" - self.parser.phase = self.parser.phases["beforeHtml"] - - def processCharacters(self, token): - self.parser.parseError("expected-doctype-but-got-chars") - self.anythingElse() - return token - - def processStartTag(self, token): - self.parser.parseError("expected-doctype-but-got-start-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEndTag(self, token): - self.parser.parseError("expected-doctype-but-got-end-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEOF(self): - self.parser.parseError("expected-doctype-but-got-eof") - self.anythingElse() - return True - - class BeforeHtmlPhase(Phase): - # helper methods - def insertHtmlElement(self): - self.tree.insertRoot(impliedTagToken("html", "StartTag")) - self.parser.phase = self.parser.phases["beforeHead"] - - # other - def processEOF(self): - self.insertHtmlElement() - return True - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.insertHtmlElement() - return token - - def processStartTag(self, token): - if token["name"] == "html": - self.parser.firstStartTag = True - self.insertHtmlElement() - return token - - def processEndTag(self, token): - if token["name"] not in ("head", "body", "html", "br"): - self.parser.parseError("unexpected-end-tag-before-html", - {"name": token["name"]}) - else: - self.insertHtmlElement() - return token - - class BeforeHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - (("head", "body", "html", "br"), self.endTagImplyHead) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.startTagHead(impliedTagToken("head", "StartTag")) - return True - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.tree.insertElement(token) - self.tree.headPointer = self.tree.openElements[-1] - self.parser.phase = self.parser.phases["inHead"] - - def startTagOther(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagImplyHead(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagOther(self, token): - self.parser.parseError("end-tag-after-implied-root", - {"name": token["name"]}) - - class InHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("title", self.startTagTitle), - (("noframes", "style"), self.startTagNoFramesStyle), - ("noscript", self.startTagNoscript), - ("script", self.startTagScript), - (("base", "basefont", "bgsound", "command", "link"), - self.startTagBaseLinkCommand), - ("meta", self.startTagMeta), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("head", self.endTagHead), - (("br", "html", "body"), self.endTagHtmlBodyBr) - ]) - self.endTagHandler.default = self.endTagOther - - # the real thing - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.parser.parseError("two-heads-are-not-better-than-one") - - def startTagBaseLinkCommand(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagMeta(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - attributes = token["data"] - if self.parser.tokenizer.stream.charEncoding[1] == "tentative": - if "charset" in attributes: - self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) - elif ("content" in attributes and - "http-equiv" in attributes and - attributes["http-equiv"].lower() == "content-type"): - # Encoding it as UTF-8 here is a hack, as really we should pass - # the abstract Unicode string, and just use the - # ContentAttrParser on that, but using UTF-8 allows all chars - # to be encoded and as a ASCII-superset works. - data = _inputstream.EncodingBytes(attributes["content"].encode("utf-8")) - parser = _inputstream.ContentAttrParser(data) - codec = parser.parse() - self.parser.tokenizer.stream.changeEncoding(codec) - - def startTagTitle(self, token): - self.parser.parseRCDataRawtext(token, "RCDATA") - - def startTagNoFramesStyle(self, token): - # Need to decide whether to implement the scripting-disabled case - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagNoscript(self, token): - if self.parser.scripting: - self.parser.parseRCDataRawtext(token, "RAWTEXT") - else: - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inHeadNoscript"] - - def startTagScript(self, token): - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState - self.parser.originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["text"] - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHead(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "head", "Expected head got %s" % node.name - self.parser.phase = self.parser.phases["afterHead"] - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.endTagHead(impliedTagToken("head")) - - class InHeadNoscriptPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("basefont", "bgsound", "link", "meta", "noframes", "style"), self.startTagBaseLinkCommand), - (("head", "noscript"), self.startTagHeadNoscript), - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("noscript", self.endTagNoscript), - ("br", self.endTagBr), - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.parser.parseError("eof-in-head-noscript") - self.anythingElse() - return True - - def processComment(self, token): - return self.parser.phases["inHead"].processComment(token) - - def processCharacters(self, token): - self.parser.parseError("char-in-head-noscript") - self.anythingElse() - return token - - def processSpaceCharacters(self, token): - return self.parser.phases["inHead"].processSpaceCharacters(token) - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBaseLinkCommand(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagHeadNoscript(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) - self.anythingElse() - return token - - def endTagNoscript(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "noscript", "Expected noscript got %s" % node.name - self.parser.phase = self.parser.phases["inHead"] - - def endTagBr(self, token): - self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - # Caller must raise parse error first! - self.endTagNoscript(impliedTagToken("noscript")) - - class AfterHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", - "style", "title"), - self.startTagFromHead), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - self.endTagHandler = _utils.MethodDispatcher([(("body", "html", "br"), - self.endTagHtmlBodyBr)]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBody(self, token): - self.parser.framesetOK = False - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inBody"] - - def startTagFrameset(self, token): - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inFrameset"] - - def startTagFromHead(self, token): - self.parser.parseError("unexpected-start-tag-out-of-my-head", - {"name": token["name"]}) - self.tree.openElements.append(self.tree.headPointer) - self.parser.phases["inHead"].processStartTag(token) - for node in self.tree.openElements[::-1]: - if node.name == "head": - self.tree.openElements.remove(node) - break - - def startTagHead(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.tree.insertElement(impliedTagToken("body", "StartTag")) - self.parser.phase = self.parser.phases["inBody"] - self.parser.framesetOK = True - - class InBodyPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody - # the really-really-really-very crazy mode - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - # Set this to the default handler - self.processSpaceCharacters = self.processSpaceCharactersNonPre - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("base", "basefont", "bgsound", "command", "link", "meta", - "script", "style", "title"), - self.startTagProcessInHead), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("address", "article", "aside", "blockquote", "center", "details", - "dir", "div", "dl", "fieldset", "figcaption", "figure", - "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", - "section", "summary", "ul"), - self.startTagCloseP), - (headingElements, self.startTagHeading), - (("pre", "listing"), self.startTagPreListing), - ("form", self.startTagForm), - (("li", "dd", "dt"), self.startTagListItem), - ("plaintext", self.startTagPlaintext), - ("a", self.startTagA), - (("b", "big", "code", "em", "font", "i", "s", "small", "strike", - "strong", "tt", "u"), self.startTagFormatting), - ("nobr", self.startTagNobr), - ("button", self.startTagButton), - (("applet", "marquee", "object"), self.startTagAppletMarqueeObject), - ("xmp", self.startTagXmp), - ("table", self.startTagTable), - (("area", "br", "embed", "img", "keygen", "wbr"), - self.startTagVoidFormatting), - (("param", "source", "track"), self.startTagParamSource), - ("input", self.startTagInput), - ("hr", self.startTagHr), - ("image", self.startTagImage), - ("isindex", self.startTagIsIndex), - ("textarea", self.startTagTextarea), - ("iframe", self.startTagIFrame), - ("noscript", self.startTagNoscript), - (("noembed", "noframes"), self.startTagRawtext), - ("select", self.startTagSelect), - (("rp", "rt"), self.startTagRpRt), - (("option", "optgroup"), self.startTagOpt), - (("math"), self.startTagMath), - (("svg"), self.startTagSvg), - (("caption", "col", "colgroup", "frame", "head", - "tbody", "td", "tfoot", "th", "thead", - "tr"), self.startTagMisplaced) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("body", self.endTagBody), - ("html", self.endTagHtml), - (("address", "article", "aside", "blockquote", "button", "center", - "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", - "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", - "section", "summary", "ul"), self.endTagBlock), - ("form", self.endTagForm), - ("p", self.endTagP), - (("dd", "dt", "li"), self.endTagListItem), - (headingElements, self.endTagHeading), - (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", - "strike", "strong", "tt", "u"), self.endTagFormatting), - (("applet", "marquee", "object"), self.endTagAppletMarqueeObject), - ("br", self.endTagBr), - ]) - self.endTagHandler.default = self.endTagOther - - def isMatchingFormattingElement(self, node1, node2): - return (node1.name == node2.name and - node1.namespace == node2.namespace and - node1.attributes == node2.attributes) - - # helper - def addFormattingElement(self, token): - self.tree.insertElement(token) - element = self.tree.openElements[-1] - - matchingElements = [] - for node in self.tree.activeFormattingElements[::-1]: - if node is Marker: - break - elif self.isMatchingFormattingElement(node, element): - matchingElements.append(node) - - assert len(matchingElements) <= 3 - if len(matchingElements) == 3: - self.tree.activeFormattingElements.remove(matchingElements[-1]) - self.tree.activeFormattingElements.append(element) - - # the real deal - def processEOF(self): - allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td", - "tfoot", "th", "thead", "tr", "body", - "html")) - for node in self.tree.openElements[::-1]: - if node.name not in allowed_elements: - self.parser.parseError("expected-closing-tag-but-got-eof") - break - # Stop parsing - - def processSpaceCharactersDropNewline(self, token): - # Sometimes (start of
, , and ",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0gTe~DWM4fkj^!0 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/more.png b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/more.png deleted file mode 100644 index 804fa226fe3ed9e6cc2bd044a848f33a2d7b4e4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=fm(z?n2}-D90{Nxdx@v7EBg&5DRB)3hmHb?jr_0{K>_1cC{J-%1r lr(<|}#G9!1a#KtW>0AF44oJ8ZkqR`E!PC{xWt~$(698mrJ|X}B diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/source.png b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/source.png deleted file mode 100644 index f7ea90419d950f9e69d977a1f5847456d96a5f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 818 zcmV-21I_%2P)@LCln44|RX7Ti z0HI3&7jPq){odH{?_{%nYVq_;n_c4WbUpvU(&Cvnj!vq|kVC-vpF6vp^;;e0mm6HW z+WPzA`AZ|;pPp$&dNjzrc??4rt`k%Q1l*u-BPD0MQ}Fbm8jnsyezNt7+u{23>t7Em zJtETY?ja9KrVs^!LJ$xEMF3-bAZO;-IQJavE60KA7fO$VY_%N)R6s>g5mW>fL4&aR z*EVgKKTBXm!=L?S0?xM zYqL@C$|EDF2q*3zWW7;PDZ}SK*IE8;i!3U62=qn80C&*I1Le7WwNP5EcX;_oh2dJn zf#HgBe4@r$GcjHjmj2vAfT%(YN?}kK=(*+1*DkNNc1H5R++vfBMhACi<5uFUU+N4+ z<&U*CPmWi}REa7C6-t>2im1CWv5Jkefxa6>)dEj-CAW wWa{_}BJ!}~75?MkfaCnj>Dn=~vkLS70Pk`;z)@TQj{pDw07*qoM6N<$f@imYHUIzs diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/style.css b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/style.css deleted file mode 100644 index 107863e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/style.css +++ /dev/null @@ -1,154 +0,0 @@ -@font-face { - font-family: 'Ubuntu'; - font-style: normal; - font-weight: normal; - src: local('Ubuntu'), local('Ubuntu-Regular'), - url('?__debugger__=yes&cmd=resource&f=ubuntu.ttf') format('truetype'); -} - -body, input { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', - 'Verdana', sans-serif; color: #000; text-align: center; - margin: 1em; padding: 0; font-size: 15px; } -h1, h2, h3 { font-family: 'Ubuntu', 'Lucida Grande', 'Lucida Sans Unicode', - 'Geneva', 'Verdana', sans-serif; font-weight: normal; } - -input { background-color: #fff; margin: 0; text-align: left; - outline: none !important; } -input[type="submit"] { padding: 3px 6px; } -a { color: #11557C; } -a:hover { color: #177199; } -pre, code, -textarea { font-family: 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', - monospace; font-size: 14px; } - -div.debugger { text-align: left; padding: 12px; margin: auto; - background-color: white; } -h1 { font-size: 36px; margin: 0 0 0.3em 0; } -div.detail { cursor: pointer; } -div.detail p { margin: 0 0 8px 13px; font-size: 14px; white-space: pre-wrap; - font-family: monospace; } -div.explanation { margin: 20px 13px; font-size: 15px; color: #555; } -div.footer { font-size: 13px; text-align: right; margin: 30px 0; - color: #86989B; } - -h2 { font-size: 16px; margin: 1.3em 0 0.0 0; padding: 9px; - background-color: #11557C; color: white; } -h2 em, h3 em { font-style: normal; color: #A5D6D9; font-weight: normal; } - -div.traceback, div.plain { border: 1px solid #ddd; margin: 0 0 1em 0; padding: 10px; } -div.plain p { margin: 0; } -div.plain textarea, -div.plain pre { margin: 10px 0 0 0; padding: 4px; - background-color: #E8EFF0; border: 1px solid #D3E7E9; } -div.plain textarea { width: 99%; height: 300px; } -div.traceback h3 { font-size: 1em; margin: 0 0 0.8em 0; } -div.traceback ul { list-style: none; margin: 0; padding: 0 0 0 1em; } -div.traceback h4 { font-size: 13px; font-weight: normal; margin: 0.7em 0 0.1em 0; } -div.traceback pre { margin: 0; padding: 5px 0 3px 15px; - background-color: #E8EFF0; border: 1px solid #D3E7E9; } -div.traceback .library .current { background: white; color: #555; } -div.traceback .expanded .current { background: #E8EFF0; color: black; } -div.traceback pre:hover { background-color: #DDECEE; color: black; cursor: pointer; } -div.traceback div.source.expanded pre + pre { border-top: none; } - -div.traceback span.ws { display: none; } -div.traceback pre.before, div.traceback pre.after { display: none; background: white; } -div.traceback div.source.expanded pre.before, -div.traceback div.source.expanded pre.after { - display: block; -} - -div.traceback div.source.expanded span.ws { - display: inline; -} - -div.traceback blockquote { margin: 1em 0 0 0; padding: 0; white-space: pre-line; } -div.traceback img { float: right; padding: 2px; margin: -3px 2px 0 0; display: none; } -div.traceback img:hover { background-color: #ddd; cursor: pointer; - border-color: #BFDDE0; } -div.traceback pre:hover img { display: block; } -div.traceback cite.filename { font-style: normal; color: #3B666B; } - -pre.console { border: 1px solid #ccc; background: white!important; - color: black; padding: 5px!important; - margin: 3px 0 0 0!important; cursor: default!important; - max-height: 400px; overflow: auto; } -pre.console form { color: #555; } -pre.console input { background-color: transparent; color: #555; - width: 90%; font-family: 'Consolas', 'Deja Vu Sans Mono', - 'Bitstream Vera Sans Mono', monospace; font-size: 14px; - border: none!important; } - -span.string { color: #30799B; } -span.number { color: #9C1A1C; } -span.help { color: #3A7734; } -span.object { color: #485F6E; } -span.extended { opacity: 0.5; } -span.extended:hover { opacity: 1; } -a.toggle { text-decoration: none; background-repeat: no-repeat; - background-position: center center; - background-image: url(?__debugger__=yes&cmd=resource&f=more.png); } -a.toggle:hover { background-color: #444; } -a.open { background-image: url(?__debugger__=yes&cmd=resource&f=less.png); } - -pre.console div.traceback, -pre.console div.box { margin: 5px 10px; white-space: normal; - border: 1px solid #11557C; padding: 10px; - font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', - 'Verdana', sans-serif; } -pre.console div.box h3, -pre.console div.traceback h3 { margin: -10px -10px 10px -10px; padding: 5px; - background: #11557C; color: white; } - -pre.console div.traceback pre:hover { cursor: default; background: #E8EFF0; } -pre.console div.traceback pre.syntaxerror { background: inherit; border: none; - margin: 20px -10px -10px -10px; - padding: 10px; border-top: 1px solid #BFDDE0; - background: #E8EFF0; } -pre.console div.noframe-traceback pre.syntaxerror { margin-top: -10px; border: none; } - -pre.console div.box pre.repr { padding: 0; margin: 0; background-color: white; border: none; } -pre.console div.box table { margin-top: 6px; } -pre.console div.box pre { border: none; } -pre.console div.box pre.help { background-color: white; } -pre.console div.box pre.help:hover { cursor: default; } -pre.console table tr { vertical-align: top; } -div.console { border: 1px solid #ccc; padding: 4px; background-color: #fafafa; } - -div.traceback pre, div.console pre { - white-space: pre-wrap; /* css-3 should we be so lucky... */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 ?? */ - white-space: -o-pre-wrap; /* Opera 7 ?? */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - _white-space: pre; /* IE only hack to re-specify in - addition to word-wrap */ -} - - -div.pin-prompt { - position: absolute; - display: none; - top: 0; - bottom: 0; - left: 0; - right: 0; - background: rgba(255, 255, 255, 0.8); -} - -div.pin-prompt .inner { - background: #eee; - padding: 10px 50px; - width: 350px; - margin: 10% auto 0 auto; - border: 1px solid #ccc; - border-radius: 2px; -} - -div.exc-divider { - margin: 0.7em 0 0 -1em; - padding: 0.5em; - background: #11557C; - color: #ddd; - border: 1px solid #ddd; -} diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/ubuntu.ttf b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/shared/ubuntu.ttf deleted file mode 100644 index 8079f938c9fa5aede9a151439f136e267958ccd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70220 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

%lg zINZYFmOi1!X^9<~q;Nv$-hQ9->=Am__pF?MPUuZuyAZ9-;NiA<1@u}yf9pq znb)v5ED9%fe51X5vEpB~{jANM-l^UG_*^BV37YxTsdZQ%+%-EJ^!3Y$YdWOZ+^-f*h^XZ31d z7}6R;dUd1XEn2og>-6jXcUfXDAJFR~!hS6oRot&Qr#P?e4e0lU;Zm08g;`a9dVA*C zz*hZkZzC(t9T;Ksf!*$w&ro@{o*;KqTWk%9i~ z=urPaE}P#xkiGEI(V_fkcKz^Be*Wc+1KCr1w5fxc!~9x7rFa8s>ZlsiCz;`bflZ@Z z`V<_za`ts=Wi`>ujT(_;%g;(^k5U5Wm?v*fA zeOvPK^}N2mP3{SAetmcDygK`ty4~NZu$`YCHPzjEp4Ck@XOBAMunKopg|IoF-*)Dz zRol03@99UtR`K_29Ny~J{@)usxCg$e?)vYQ&zJ6;l)Ftqo#5cVJ|?;I9m8Ef2C6{# z;MZUK%kLh1gV(pHvjml&zP7#pwZ$#ca>W~NG3aTHIsNzm;_V(Yx{jZgfPjAa@Jtc;|&wjh|WGCr9=I>DD`8$>6I$2M8J4Iud9(5caK~K~D{8sDU zZl~)&afZfMzL(G%jZ@yQXK9|T=6+D0&vmNNR|S6fkm}6ORYmv))$5)w)gM)j@&&T^ z<2o!|q{`G!C~xBW%TH-G>1V>l%476pI>N0Q<7oDExHAO)^_ci88^^N&rh{I3A-@_~6)o@Grxkl!9t4jV-b@y+nL)@d?I<4_->9tZ?BHW+T)9~-&g4Aq5BoP7wF&J|Ga&VfA7kaPT}{5 H?s(!~BBTR` diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/tbtools.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/tbtools.py deleted file mode 100644 index b34403d..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/debug/tbtools.py +++ /dev/null @@ -1,628 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.debug.tbtools - ~~~~~~~~~~~~~~~~~~~~~~ - - This module provides various traceback related utility functions. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import inspect -import json -import os -import re -import sys -import sysconfig -import traceback -from tokenize import TokenError - -from .._compat import PY2 -from .._compat import range_type -from .._compat import reraise -from .._compat import string_types -from .._compat import text_type -from .._compat import to_native -from .._compat import to_unicode -from ..filesystem import get_filesystem_encoding -from ..utils import cached_property -from ..utils import escape -from .console import Console - - -_coding_re = re.compile(br"coding[:=]\s*([-\w.]+)") -_line_re = re.compile(br"^(.*?)$", re.MULTILINE) -_funcdef_re = re.compile(r"^(\s*def\s)|(.*(? - - - %(title)s // Werkzeug Debugger - - - - - - - - -

-""" -FOOTER = u"""\ - -
- -
-
-

Console Locked

-

- The console is locked and needs to be unlocked by entering the PIN. - You can find the PIN printed out on the standard output of your - shell that runs the server. -

-

PIN: - - -

-
-
- - -""" - -PAGE_HTML = ( - HEADER - + u"""\ -

%(exception_type)s

-
-

%(exception)s

-
-

Traceback (most recent call last)

-%(summary)s -
-
-

- - This is the Copy/Paste friendly version of the traceback. You can also paste this traceback into - a gist: - -

- -
-
-
- The debugger caught an exception in your WSGI application. You can now - look at the traceback which led to the error. - If you enable JavaScript you can also use additional features such as code - execution (if the evalex feature is enabled), automatic pasting of the - exceptions and much more. -
-""" - + FOOTER - + """ - -""" -) - -CONSOLE_HTML = ( - HEADER - + u"""\ -

Interactive Console

-
-In this console you can execute Python expressions in the context of the -application. The initial namespace was created by the debugger automatically. -
-
The Console requires JavaScript.
-""" - + FOOTER -) - -SUMMARY_HTML = u"""\ -
- %(title)s -
    %(frames)s
- %(description)s -
-""" - -FRAME_HTML = u"""\ -
-

File "%(filename)s", - line %(lineno)s, - in %(function_name)s

-
%(lines)s
-
-""" - -SOURCE_LINE_HTML = u"""\ - - %(lineno)s - %(code)s - -""" - - -def render_console_html(secret, evalex_trusted=True): - return CONSOLE_HTML % { - "evalex": "true", - "evalex_trusted": "true" if evalex_trusted else "false", - "console": "true", - "title": "Console", - "secret": secret, - "traceback_id": -1, - } - - -def get_current_traceback( - ignore_system_exceptions=False, show_hidden_frames=False, skip=0 -): - """Get the current exception info as `Traceback` object. Per default - calling this method will reraise system exceptions such as generator exit, - system exit or others. This behavior can be disabled by passing `False` - to the function as first parameter. - """ - exc_type, exc_value, tb = sys.exc_info() - if ignore_system_exceptions and exc_type in system_exceptions: - reraise(exc_type, exc_value, tb) - for _ in range_type(skip): - if tb.tb_next is None: - break - tb = tb.tb_next - tb = Traceback(exc_type, exc_value, tb) - if not show_hidden_frames: - tb.filter_hidden_frames() - return tb - - -class Line(object): - """Helper for the source renderer.""" - - __slots__ = ("lineno", "code", "in_frame", "current") - - def __init__(self, lineno, code): - self.lineno = lineno - self.code = code - self.in_frame = False - self.current = False - - @property - def classes(self): - rv = ["line"] - if self.in_frame: - rv.append("in-frame") - if self.current: - rv.append("current") - return rv - - def render(self): - return SOURCE_LINE_HTML % { - "classes": u" ".join(self.classes), - "lineno": self.lineno, - "code": escape(self.code), - } - - -class Traceback(object): - """Wraps a traceback.""" - - def __init__(self, exc_type, exc_value, tb): - self.exc_type = exc_type - self.exc_value = exc_value - self.tb = tb - - exception_type = exc_type.__name__ - if exc_type.__module__ not in {"builtins", "__builtin__", "exceptions"}: - exception_type = exc_type.__module__ + "." + exception_type - self.exception_type = exception_type - - self.groups = [] - memo = set() - while True: - self.groups.append(Group(exc_type, exc_value, tb)) - memo.add(id(exc_value)) - if PY2: - break - exc_value = exc_value.__cause__ or exc_value.__context__ - if exc_value is None or id(exc_value) in memo: - break - exc_type = type(exc_value) - tb = exc_value.__traceback__ - self.groups.reverse() - self.frames = [frame for group in self.groups for frame in group.frames] - - def filter_hidden_frames(self): - """Remove the frames according to the paste spec.""" - for group in self.groups: - group.filter_hidden_frames() - - self.frames[:] = [frame for group in self.groups for frame in group.frames] - - @property - def is_syntax_error(self): - """Is it a syntax error?""" - return isinstance(self.exc_value, SyntaxError) - - @property - def exception(self): - """String representation of the final exception.""" - return self.groups[-1].exception - - def log(self, logfile=None): - """Log the ASCII traceback into a file object.""" - if logfile is None: - logfile = sys.stderr - tb = self.plaintext.rstrip() + u"\n" - logfile.write(to_native(tb, "utf-8", "replace")) - - def paste(self): - """Create a paste and return the paste id.""" - data = json.dumps( - { - "description": "Werkzeug Internal Server Error", - "public": False, - "files": {"traceback.txt": {"content": self.plaintext}}, - } - ).encode("utf-8") - try: - from urllib2 import urlopen - except ImportError: - from urllib.request import urlopen - rv = urlopen("https://api.github.com/gists", data=data) - resp = json.loads(rv.read().decode("utf-8")) - rv.close() - return {"url": resp["html_url"], "id": resp["id"]} - - def render_summary(self, include_title=True): - """Render the traceback for the interactive console.""" - title = "" - classes = ["traceback"] - if not self.frames: - classes.append("noframe-traceback") - frames = [] - else: - library_frames = sum(frame.is_library for frame in self.frames) - mark_lib = 0 < library_frames < len(self.frames) - frames = [group.render(mark_lib=mark_lib) for group in self.groups] - - if include_title: - if self.is_syntax_error: - title = u"Syntax Error" - else: - title = u"Traceback (most recent call last):" - - if self.is_syntax_error: - description_wrapper = u"
%s
" - else: - description_wrapper = u"
%s
" - - return SUMMARY_HTML % { - "classes": u" ".join(classes), - "title": u"

%s

" % title if title else u"", - "frames": u"\n".join(frames), - "description": description_wrapper % escape(self.exception), - } - - def render_full(self, evalex=False, secret=None, evalex_trusted=True): - """Render the Full HTML page with the traceback info.""" - exc = escape(self.exception) - return PAGE_HTML % { - "evalex": "true" if evalex else "false", - "evalex_trusted": "true" if evalex_trusted else "false", - "console": "false", - "title": exc, - "exception": exc, - "exception_type": escape(self.exception_type), - "summary": self.render_summary(include_title=False), - "plaintext": escape(self.plaintext), - "plaintext_cs": re.sub("-{2,}", "-", self.plaintext), - "traceback_id": self.id, - "secret": secret, - } - - @cached_property - def plaintext(self): - return u"\n".join([group.render_text() for group in self.groups]) - - @property - def id(self): - return id(self) - - -class Group(object): - """A group of frames for an exception in a traceback. On Python 3, - if the exception has a ``__cause__`` or ``__context__``, there are - multiple exception groups. - """ - - def __init__(self, exc_type, exc_value, tb): - self.exc_type = exc_type - self.exc_value = exc_value - self.info = None - if not PY2: - if exc_value.__cause__ is not None: - self.info = ( - u"The above exception was the direct cause of the" - u" following exception" - ) - elif exc_value.__context__ is not None: - self.info = ( - u"During handling of the above exception, another" - u" exception occurred" - ) - - self.frames = [] - while tb is not None: - self.frames.append(Frame(exc_type, exc_value, tb)) - tb = tb.tb_next - - def filter_hidden_frames(self): - new_frames = [] - hidden = False - - for frame in self.frames: - hide = frame.hide - if hide in ("before", "before_and_this"): - new_frames = [] - hidden = False - if hide == "before_and_this": - continue - elif hide in ("reset", "reset_and_this"): - hidden = False - if hide == "reset_and_this": - continue - elif hide in ("after", "after_and_this"): - hidden = True - if hide == "after_and_this": - continue - elif hide or hidden: - continue - new_frames.append(frame) - - # if we only have one frame and that frame is from the codeop - # module, remove it. - if len(new_frames) == 1 and self.frames[0].module == "codeop": - del self.frames[:] - - # if the last frame is missing something went terrible wrong :( - elif self.frames[-1] in new_frames: - self.frames[:] = new_frames - - @property - def exception(self): - """String representation of the exception.""" - buf = traceback.format_exception_only(self.exc_type, self.exc_value) - rv = "".join(buf).strip() - return to_unicode(rv, "utf-8", "replace") - - def render(self, mark_lib=True): - out = [] - if self.info is not None: - out.append(u'
  • %s:
    ' % self.info) - for frame in self.frames: - out.append( - u"%s" - % ( - u' title="%s"' % escape(frame.info) if frame.info else u"", - frame.render(mark_lib=mark_lib), - ) - ) - return u"\n".join(out) - - def render_text(self): - out = [] - if self.info is not None: - out.append(u"\n%s:\n" % self.info) - out.append(u"Traceback (most recent call last):") - for frame in self.frames: - out.append(frame.render_text()) - out.append(self.exception) - return u"\n".join(out) - - -class Frame(object): - """A single frame in a traceback.""" - - def __init__(self, exc_type, exc_value, tb): - self.lineno = tb.tb_lineno - self.function_name = tb.tb_frame.f_code.co_name - self.locals = tb.tb_frame.f_locals - self.globals = tb.tb_frame.f_globals - - fn = inspect.getsourcefile(tb) or inspect.getfile(tb) - if fn[-4:] in (".pyo", ".pyc"): - fn = fn[:-1] - # if it's a file on the file system resolve the real filename. - if os.path.isfile(fn): - fn = os.path.realpath(fn) - self.filename = to_unicode(fn, get_filesystem_encoding()) - self.module = self.globals.get("__name__", self.locals.get("__name__")) - self.loader = self.globals.get("__loader__", self.locals.get("__loader__")) - self.code = tb.tb_frame.f_code - - # support for paste's traceback extensions - self.hide = self.locals.get("__traceback_hide__", False) - info = self.locals.get("__traceback_info__") - if info is not None: - info = to_unicode(info, "utf-8", "replace") - self.info = info - - def render(self, mark_lib=True): - """Render a single frame in a traceback.""" - return FRAME_HTML % { - "id": self.id, - "filename": escape(self.filename), - "lineno": self.lineno, - "function_name": escape(self.function_name), - "lines": self.render_line_context(), - "library": "library" if mark_lib and self.is_library else "", - } - - @cached_property - def is_library(self): - return any( - self.filename.startswith(path) for path in sysconfig.get_paths().values() - ) - - def render_text(self): - return u' File "%s", line %s, in %s\n %s' % ( - self.filename, - self.lineno, - self.function_name, - self.current_line.strip(), - ) - - def render_line_context(self): - before, current, after = self.get_context_lines() - rv = [] - - def render_line(line, cls): - line = line.expandtabs().rstrip() - stripped_line = line.strip() - prefix = len(line) - len(stripped_line) - rv.append( - '
    %s%s
    ' - % (cls, " " * prefix, escape(stripped_line) or " ") - ) - - for line in before: - render_line(line, "before") - render_line(current, "current") - for line in after: - render_line(line, "after") - - return "\n".join(rv) - - def get_annotated_lines(self): - """Helper function that returns lines with extra information.""" - lines = [Line(idx + 1, x) for idx, x in enumerate(self.sourcelines)] - - # find function definition and mark lines - if hasattr(self.code, "co_firstlineno"): - lineno = self.code.co_firstlineno - 1 - while lineno > 0: - if _funcdef_re.match(lines[lineno].code): - break - lineno -= 1 - try: - offset = len(inspect.getblock([x.code + "\n" for x in lines[lineno:]])) - except TokenError: - offset = 0 - for line in lines[lineno : lineno + offset]: - line.in_frame = True - - # mark current line - try: - lines[self.lineno - 1].current = True - except IndexError: - pass - - return lines - - def eval(self, code, mode="single"): - """Evaluate code in the context of the frame.""" - if isinstance(code, string_types): - if PY2 and isinstance(code, text_type): # noqa - code = UTF8_COOKIE + code.encode("utf-8") - code = compile(code, "", mode) - return eval(code, self.globals, self.locals) - - @cached_property - def sourcelines(self): - """The sourcecode of the file as list of unicode strings.""" - # get sourcecode from loader or file - source = None - if self.loader is not None: - try: - if hasattr(self.loader, "get_source"): - source = self.loader.get_source(self.module) - elif hasattr(self.loader, "get_source_by_code"): - source = self.loader.get_source_by_code(self.code) - except Exception: - # we munch the exception so that we don't cause troubles - # if the loader is broken. - pass - - if source is None: - try: - with open( - to_native(self.filename, get_filesystem_encoding()), mode="rb" - ) as f: - source = f.read() - except IOError: - return [] - - # already unicode? return right away - if isinstance(source, text_type): - return source.splitlines() - - # yes. it should be ascii, but we don't want to reject too many - # characters in the debugger if something breaks - charset = "utf-8" - if source.startswith(UTF8_COOKIE): - source = source[3:] - else: - for idx, match in enumerate(_line_re.finditer(source)): - match = _coding_re.search(match.group()) - if match is not None: - charset = match.group(1) - break - if idx > 1: - break - - # on broken cookies we fall back to utf-8 too - charset = to_native(charset) - try: - codecs.lookup(charset) - except LookupError: - charset = "utf-8" - - return source.decode(charset, "replace").splitlines() - - def get_context_lines(self, context=5): - before = self.sourcelines[self.lineno - context - 1 : self.lineno - 1] - past = self.sourcelines[self.lineno : self.lineno + context] - return (before, self.current_line, past) - - @property - def current_line(self): - try: - return self.sourcelines[self.lineno - 1] - except IndexError: - return u"" - - @cached_property - def console(self): - return Console(self.globals, self.locals) - - @property - def id(self): - return id(self) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/exceptions.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/exceptions.py deleted file mode 100644 index 82e99c2..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/exceptions.py +++ /dev/null @@ -1,829 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.exceptions - ~~~~~~~~~~~~~~~~~~~ - - This module implements a number of Python exceptions you can raise from - within your views to trigger a standard non-200 response. - - - Usage Example - ------------- - - :: - - from werkzeug.wrappers import BaseRequest - from werkzeug.wsgi import responder - from werkzeug.exceptions import HTTPException, NotFound - - def view(request): - raise NotFound() - - @responder - def application(environ, start_response): - request = BaseRequest(environ) - try: - return view(request) - except HTTPException as e: - return e - - - As you can see from this example those exceptions are callable WSGI - applications. Because of Python 2.4 compatibility those do not extend - from the response objects but only from the python exception class. - - As a matter of fact they are not Werkzeug response objects. However you - can get a response object by calling ``get_response()`` on a HTTP - exception. - - Keep in mind that you have to pass an environment to ``get_response()`` - because some errors fetch additional information from the WSGI - environment. - - If you want to hook in a different exception page to say, a 404 status - code, you can add a second except for a specific subclass of an error:: - - @responder - def application(environ, start_response): - request = BaseRequest(environ) - try: - return view(request) - except NotFound, e: - return not_found(request) - except HTTPException, e: - return e - - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import sys -from datetime import datetime - -from ._compat import implements_to_string -from ._compat import integer_types -from ._compat import iteritems -from ._compat import text_type -from ._internal import _get_environ -from .utils import escape - - -@implements_to_string -class HTTPException(Exception): - """Baseclass for all HTTP exceptions. This exception can be called as WSGI - application to render a default error page or you can catch the subclasses - of it independently and render nicer error messages. - """ - - code = None - description = None - - def __init__(self, description=None, response=None): - super(HTTPException, self).__init__() - if description is not None: - self.description = description - self.response = response - - @classmethod - def wrap(cls, exception, name=None): - """Create an exception that is a subclass of the calling HTTP - exception and the ``exception`` argument. - - The first argument to the class will be passed to the - wrapped ``exception``, the rest to the HTTP exception. If - ``e.args`` is not empty and ``e.show_exception`` is ``True``, - the wrapped exception message is added to the HTTP error - description. - - .. versionchanged:: 0.15.5 - The ``show_exception`` attribute controls whether the - description includes the wrapped exception message. - - .. versionchanged:: 0.15.0 - The description includes the wrapped exception message. - """ - - class newcls(cls, exception): - _description = cls.description - show_exception = False - - def __init__(self, arg=None, *args, **kwargs): - super(cls, self).__init__(*args, **kwargs) - - if arg is None: - exception.__init__(self) - else: - exception.__init__(self, arg) - - @property - def description(self): - if self.show_exception: - return "{}\n{}: {}".format( - self._description, exception.__name__, exception.__str__(self) - ) - - return self._description - - @description.setter - def description(self, value): - self._description = value - - newcls.__module__ = sys._getframe(1).f_globals.get("__name__") - name = name or cls.__name__ + exception.__name__ - newcls.__name__ = newcls.__qualname__ = name - return newcls - - @property - def name(self): - """The status name.""" - from .http import HTTP_STATUS_CODES - - return HTTP_STATUS_CODES.get(self.code, "Unknown Error") - - def get_description(self, environ=None): - """Get the description.""" - return u"

    %s

    " % escape(self.description).replace("\n", "
    ") - - def get_body(self, environ=None): - """Get the HTML body.""" - return text_type( - ( - u'\n' - u"%(code)s %(name)s\n" - u"

    %(name)s

    \n" - u"%(description)s\n" - ) - % { - "code": self.code, - "name": escape(self.name), - "description": self.get_description(environ), - } - ) - - def get_headers(self, environ=None): - """Get a list of headers.""" - return [("Content-Type", "text/html; charset=utf-8")] - - def get_response(self, environ=None): - """Get a response object. If one was passed to the exception - it's returned directly. - - :param environ: the optional environ for the request. This - can be used to modify the response depending - on how the request looked like. - :return: a :class:`Response` object or a subclass thereof. - """ - from .wrappers.response import Response - - if self.response is not None: - return self.response - if environ is not None: - environ = _get_environ(environ) - headers = self.get_headers(environ) - return Response(self.get_body(environ), self.code, headers) - - def __call__(self, environ, start_response): - """Call the exception as WSGI application. - - :param environ: the WSGI environment. - :param start_response: the response callable provided by the WSGI - server. - """ - response = self.get_response(environ) - return response(environ, start_response) - - def __str__(self): - code = self.code if self.code is not None else "???" - return "%s %s: %s" % (code, self.name, self.description) - - def __repr__(self): - code = self.code if self.code is not None else "???" - return "<%s '%s: %s'>" % (self.__class__.__name__, code, self.name) - - -class BadRequest(HTTPException): - """*400* `Bad Request` - - Raise if the browser sends something to the application the application - or server cannot handle. - """ - - code = 400 - description = ( - "The browser (or proxy) sent a request that this server could " - "not understand." - ) - - -class ClientDisconnected(BadRequest): - """Internal exception that is raised if Werkzeug detects a disconnected - client. Since the client is already gone at that point attempting to - send the error message to the client might not work and might ultimately - result in another exception in the server. Mainly this is here so that - it is silenced by default as far as Werkzeug is concerned. - - Since disconnections cannot be reliably detected and are unspecified - by WSGI to a large extent this might or might not be raised if a client - is gone. - - .. versionadded:: 0.8 - """ - - -class SecurityError(BadRequest): - """Raised if something triggers a security error. This is otherwise - exactly like a bad request error. - - .. versionadded:: 0.9 - """ - - -class BadHost(BadRequest): - """Raised if the submitted host is badly formatted. - - .. versionadded:: 0.11.2 - """ - - -class Unauthorized(HTTPException): - """*401* ``Unauthorized`` - - Raise if the user is not authorized to access a resource. - - The ``www_authenticate`` argument should be used to set the - ``WWW-Authenticate`` header. This is used for HTTP basic auth and - other schemes. Use :class:`~werkzeug.datastructures.WWWAuthenticate` - to create correctly formatted values. Strictly speaking a 401 - response is invalid if it doesn't provide at least one value for - this header, although real clients typically don't care. - - :param description: Override the default message used for the body - of the response. - :param www-authenticate: A single value, or list of values, for the - WWW-Authenticate header. - - .. versionchanged:: 0.15.3 - If the ``www_authenticate`` argument is not set, the - ``WWW-Authenticate`` header is not set. - - .. versionchanged:: 0.15.3 - The ``response`` argument was restored. - - .. versionchanged:: 0.15.1 - ``description`` was moved back as the first argument, restoring - its previous position. - - .. versionchanged:: 0.15.0 - ``www_authenticate`` was added as the first argument, ahead of - ``description``. - """ - - code = 401 - description = ( - "The server could not verify that you are authorized to access" - " the URL requested. You either supplied the wrong credentials" - " (e.g. a bad password), or your browser doesn't understand" - " how to supply the credentials required." - ) - - def __init__(self, description=None, response=None, www_authenticate=None): - HTTPException.__init__(self, description, response) - - if www_authenticate is not None: - if not isinstance(www_authenticate, (tuple, list)): - www_authenticate = (www_authenticate,) - - self.www_authenticate = www_authenticate - - def get_headers(self, environ=None): - headers = HTTPException.get_headers(self, environ) - if self.www_authenticate: - headers.append( - ("WWW-Authenticate", ", ".join([str(x) for x in self.www_authenticate])) - ) - return headers - - -class Forbidden(HTTPException): - """*403* `Forbidden` - - Raise if the user doesn't have the permission for the requested resource - but was authenticated. - """ - - code = 403 - description = ( - "You don't have the permission to access the requested" - " resource. It is either read-protected or not readable by the" - " server." - ) - - -class NotFound(HTTPException): - """*404* `Not Found` - - Raise if a resource does not exist and never existed. - """ - - code = 404 - description = ( - "The requested URL was not found on the server. If you entered" - " the URL manually please check your spelling and try again." - ) - - -class MethodNotAllowed(HTTPException): - """*405* `Method Not Allowed` - - Raise if the server used a method the resource does not handle. For - example `POST` if the resource is view only. Especially useful for REST. - - The first argument for this exception should be a list of allowed methods. - Strictly speaking the response would be invalid if you don't provide valid - methods in the header which you can do with that list. - """ - - code = 405 - description = "The method is not allowed for the requested URL." - - def __init__(self, valid_methods=None, description=None): - """Takes an optional list of valid http methods - starting with werkzeug 0.3 the list will be mandatory.""" - HTTPException.__init__(self, description) - self.valid_methods = valid_methods - - def get_headers(self, environ=None): - headers = HTTPException.get_headers(self, environ) - if self.valid_methods: - headers.append(("Allow", ", ".join(self.valid_methods))) - return headers - - -class NotAcceptable(HTTPException): - """*406* `Not Acceptable` - - Raise if the server can't return any content conforming to the - `Accept` headers of the client. - """ - - code = 406 - - description = ( - "The resource identified by the request is only capable of" - " generating response entities which have content" - " characteristics not acceptable according to the accept" - " headers sent in the request." - ) - - -class RequestTimeout(HTTPException): - """*408* `Request Timeout` - - Raise to signalize a timeout. - """ - - code = 408 - description = ( - "The server closed the network connection because the browser" - " didn't finish the request within the specified time." - ) - - -class Conflict(HTTPException): - """*409* `Conflict` - - Raise to signal that a request cannot be completed because it conflicts - with the current state on the server. - - .. versionadded:: 0.7 - """ - - code = 409 - description = ( - "A conflict happened while processing the request. The" - " resource might have been modified while the request was being" - " processed." - ) - - -class Gone(HTTPException): - """*410* `Gone` - - Raise if a resource existed previously and went away without new location. - """ - - code = 410 - description = ( - "The requested URL is no longer available on this server and" - " there is no forwarding address. If you followed a link from a" - " foreign page, please contact the author of this page." - ) - - -class LengthRequired(HTTPException): - """*411* `Length Required` - - Raise if the browser submitted data but no ``Content-Length`` header which - is required for the kind of processing the server does. - """ - - code = 411 - description = ( - "A request with this method requires a valid Content-" - "Length header." - ) - - -class PreconditionFailed(HTTPException): - """*412* `Precondition Failed` - - Status code used in combination with ``If-Match``, ``If-None-Match``, or - ``If-Unmodified-Since``. - """ - - code = 412 - description = ( - "The precondition on the request for the URL failed positive evaluation." - ) - - -class RequestEntityTooLarge(HTTPException): - """*413* `Request Entity Too Large` - - The status code one should return if the data submitted exceeded a given - limit. - """ - - code = 413 - description = "The data value transmitted exceeds the capacity limit." - - -class RequestURITooLarge(HTTPException): - """*414* `Request URI Too Large` - - Like *413* but for too long URLs. - """ - - code = 414 - description = ( - "The length of the requested URL exceeds the capacity limit for" - " this server. The request cannot be processed." - ) - - -class UnsupportedMediaType(HTTPException): - """*415* `Unsupported Media Type` - - The status code returned if the server is unable to handle the media type - the client transmitted. - """ - - code = 415 - description = ( - "The server does not support the media type transmitted in the request." - ) - - -class RequestedRangeNotSatisfiable(HTTPException): - """*416* `Requested Range Not Satisfiable` - - The client asked for an invalid part of the file. - - .. versionadded:: 0.7 - """ - - code = 416 - description = "The server cannot provide the requested range." - - def __init__(self, length=None, units="bytes", description=None): - """Takes an optional `Content-Range` header value based on ``length`` - parameter. - """ - HTTPException.__init__(self, description) - self.length = length - self.units = units - - def get_headers(self, environ=None): - headers = HTTPException.get_headers(self, environ) - if self.length is not None: - headers.append(("Content-Range", "%s */%d" % (self.units, self.length))) - return headers - - -class ExpectationFailed(HTTPException): - """*417* `Expectation Failed` - - The server cannot meet the requirements of the Expect request-header. - - .. versionadded:: 0.7 - """ - - code = 417 - description = "The server could not meet the requirements of the Expect header" - - -class ImATeapot(HTTPException): - """*418* `I'm a teapot` - - The server should return this if it is a teapot and someone attempted - to brew coffee with it. - - .. versionadded:: 0.7 - """ - - code = 418 - description = "This server is a teapot, not a coffee machine" - - -class UnprocessableEntity(HTTPException): - """*422* `Unprocessable Entity` - - Used if the request is well formed, but the instructions are otherwise - incorrect. - """ - - code = 422 - description = ( - "The request was well-formed but was unable to be followed due" - " to semantic errors." - ) - - -class Locked(HTTPException): - """*423* `Locked` - - Used if the resource that is being accessed is locked. - """ - - code = 423 - description = "The resource that is being accessed is locked." - - -class FailedDependency(HTTPException): - """*424* `Failed Dependency` - - Used if the method could not be performed on the resource - because the requested action depended on another action and that action failed. - """ - - code = 424 - description = ( - "The method could not be performed on the resource because the" - " requested action depended on another action and that action" - " failed." - ) - - -class PreconditionRequired(HTTPException): - """*428* `Precondition Required` - - The server requires this request to be conditional, typically to prevent - the lost update problem, which is a race condition between two or more - clients attempting to update a resource through PUT or DELETE. By requiring - each client to include a conditional header ("If-Match" or "If-Unmodified- - Since") with the proper value retained from a recent GET request, the - server ensures that each client has at least seen the previous revision of - the resource. - """ - - code = 428 - description = ( - "This request is required to be conditional; try using" - ' "If-Match" or "If-Unmodified-Since".' - ) - - -class _RetryAfter(HTTPException): - """Adds an optional ``retry_after`` parameter which will set the - ``Retry-After`` header. May be an :class:`int` number of seconds or - a :class:`~datetime.datetime`. - """ - - def __init__(self, description=None, response=None, retry_after=None): - super(_RetryAfter, self).__init__(description, response) - self.retry_after = retry_after - - def get_headers(self, environ=None): - headers = super(_RetryAfter, self).get_headers(environ) - - if self.retry_after: - if isinstance(self.retry_after, datetime): - from .http import http_date - - value = http_date(self.retry_after) - else: - value = str(self.retry_after) - - headers.append(("Retry-After", value)) - - return headers - - -class TooManyRequests(_RetryAfter): - """*429* `Too Many Requests` - - The server is limiting the rate at which this user receives - responses, and this request exceeds that rate. (The server may use - any convenient method to identify users and their request rates). - The server may include a "Retry-After" header to indicate how long - the user should wait before retrying. - - :param retry_after: If given, set the ``Retry-After`` header to this - value. May be an :class:`int` number of seconds or a - :class:`~datetime.datetime`. - - .. versionchanged:: 1.0 - Added ``retry_after`` parameter. - """ - - code = 429 - description = "This user has exceeded an allotted request count. Try again later." - - -class RequestHeaderFieldsTooLarge(HTTPException): - """*431* `Request Header Fields Too Large` - - The server refuses to process the request because the header fields are too - large. One or more individual fields may be too large, or the set of all - headers is too large. - """ - - code = 431 - description = "One or more header fields exceeds the maximum size." - - -class UnavailableForLegalReasons(HTTPException): - """*451* `Unavailable For Legal Reasons` - - This status code indicates that the server is denying access to the - resource as a consequence of a legal demand. - """ - - code = 451 - description = "Unavailable for legal reasons." - - -class InternalServerError(HTTPException): - """*500* `Internal Server Error` - - Raise if an internal server error occurred. This is a good fallback if an - unknown error occurred in the dispatcher. - - .. versionchanged:: 1.0.0 - Added the :attr:`original_exception` attribute. - """ - - code = 500 - description = ( - "The server encountered an internal error and was unable to" - " complete your request. Either the server is overloaded or" - " there is an error in the application." - ) - - def __init__(self, description=None, response=None, original_exception=None): - #: The original exception that caused this 500 error. Can be - #: used by frameworks to provide context when handling - #: unexpected errors. - self.original_exception = original_exception - super(InternalServerError, self).__init__( - description=description, response=response - ) - - -class NotImplemented(HTTPException): - """*501* `Not Implemented` - - Raise if the application does not support the action requested by the - browser. - """ - - code = 501 - description = "The server does not support the action requested by the browser." - - -class BadGateway(HTTPException): - """*502* `Bad Gateway` - - If you do proxying in your application you should return this status code - if you received an invalid response from the upstream server it accessed - in attempting to fulfill the request. - """ - - code = 502 - description = ( - "The proxy server received an invalid response from an upstream server." - ) - - -class ServiceUnavailable(_RetryAfter): - """*503* `Service Unavailable` - - Status code you should return if a service is temporarily - unavailable. - - :param retry_after: If given, set the ``Retry-After`` header to this - value. May be an :class:`int` number of seconds or a - :class:`~datetime.datetime`. - - .. versionchanged:: 1.0 - Added ``retry_after`` parameter. - """ - - code = 503 - description = ( - "The server is temporarily unable to service your request due" - " to maintenance downtime or capacity problems. Please try" - " again later." - ) - - -class GatewayTimeout(HTTPException): - """*504* `Gateway Timeout` - - Status code you should return if a connection to an upstream server - times out. - """ - - code = 504 - description = "The connection to an upstream server timed out." - - -class HTTPVersionNotSupported(HTTPException): - """*505* `HTTP Version Not Supported` - - The server does not support the HTTP protocol version used in the request. - """ - - code = 505 - description = ( - "The server does not support the HTTP protocol version used in the request." - ) - - -default_exceptions = {} -__all__ = ["HTTPException"] - - -def _find_exceptions(): - for _name, obj in iteritems(globals()): - try: - is_http_exception = issubclass(obj, HTTPException) - except TypeError: - is_http_exception = False - if not is_http_exception or obj.code is None: - continue - __all__.append(obj.__name__) - old_obj = default_exceptions.get(obj.code, None) - if old_obj is not None and issubclass(obj, old_obj): - continue - default_exceptions[obj.code] = obj - - -_find_exceptions() -del _find_exceptions - - -class Aborter(object): - """When passed a dict of code -> exception items it can be used as - callable that raises exceptions. If the first argument to the - callable is an integer it will be looked up in the mapping, if it's - a WSGI application it will be raised in a proxy exception. - - The rest of the arguments are forwarded to the exception constructor. - """ - - def __init__(self, mapping=None, extra=None): - if mapping is None: - mapping = default_exceptions - self.mapping = dict(mapping) - if extra is not None: - self.mapping.update(extra) - - def __call__(self, code, *args, **kwargs): - if not args and not kwargs and not isinstance(code, integer_types): - raise HTTPException(response=code) - if code not in self.mapping: - raise LookupError("no exception for %r" % code) - raise self.mapping[code](*args, **kwargs) - - -def abort(status, *args, **kwargs): - """Raises an :py:exc:`HTTPException` for the given status code or WSGI - application. - - If a status code is given, it will be looked up in the list of - exceptions and will raise that exception. If passed a WSGI application, - it will wrap it in a proxy WSGI exception and raise that:: - - abort(404) # 404 Not Found - abort(Response('Hello World')) - - """ - return _aborter(status, *args, **kwargs) - - -_aborter = Aborter() - -#: An exception that is used to signal both a :exc:`KeyError` and a -#: :exc:`BadRequest`. Used by many of the datastructures. -BadRequestKeyError = BadRequest.wrap(KeyError) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/filesystem.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/filesystem.py deleted file mode 100644 index d016cae..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/filesystem.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.filesystem - ~~~~~~~~~~~~~~~~~~~ - - Various utilities for the local filesystem. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import sys -import warnings - -# We do not trust traditional unixes. -has_likely_buggy_unicode_filesystem = ( - sys.platform.startswith("linux") or "bsd" in sys.platform -) - - -def _is_ascii_encoding(encoding): - """Given an encoding this figures out if the encoding is actually ASCII (which - is something we don't actually want in most cases). This is necessary - because ASCII comes under many names such as ANSI_X3.4-1968. - """ - if encoding is None: - return False - try: - return codecs.lookup(encoding).name == "ascii" - except LookupError: - return False - - -class BrokenFilesystemWarning(RuntimeWarning, UnicodeWarning): - """The warning used by Werkzeug to signal a broken filesystem. Will only be - used once per runtime.""" - - -_warned_about_filesystem_encoding = False - - -def get_filesystem_encoding(): - """Returns the filesystem encoding that should be used. Note that this is - different from the Python understanding of the filesystem encoding which - might be deeply flawed. Do not use this value against Python's unicode APIs - because it might be different. See :ref:`filesystem-encoding` for the exact - behavior. - - The concept of a filesystem encoding in generally is not something you - should rely on. As such if you ever need to use this function except for - writing wrapper code reconsider. - """ - global _warned_about_filesystem_encoding - rv = sys.getfilesystemencoding() - if has_likely_buggy_unicode_filesystem and not rv or _is_ascii_encoding(rv): - if not _warned_about_filesystem_encoding: - warnings.warn( - "Detected a misconfigured UNIX filesystem: Will use" - " UTF-8 as filesystem encoding instead of {0!r}".format(rv), - BrokenFilesystemWarning, - ) - _warned_about_filesystem_encoding = True - return "utf-8" - return rv diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/formparser.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/formparser.py deleted file mode 100644 index ffdb9b0..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/formparser.py +++ /dev/null @@ -1,584 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.formparser - ~~~~~~~~~~~~~~~~~~~ - - This module implements the form parsing. It supports url-encoded forms - as well as non-nested multipart uploads. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import re -from functools import update_wrapper -from itertools import chain -from itertools import repeat -from itertools import tee - -from . import exceptions -from ._compat import BytesIO -from ._compat import text_type -from ._compat import to_native -from .datastructures import FileStorage -from .datastructures import Headers -from .datastructures import MultiDict -from .http import parse_options_header -from .urls import url_decode_stream -from .wsgi import get_content_length -from .wsgi import get_input_stream -from .wsgi import make_line_iter - -# there are some platforms where SpooledTemporaryFile is not available. -# In that case we need to provide a fallback. -try: - from tempfile import SpooledTemporaryFile -except ImportError: - from tempfile import TemporaryFile - - SpooledTemporaryFile = None - - -#: an iterator that yields empty strings -_empty_string_iter = repeat("") - -#: a regular expression for multipart boundaries -_multipart_boundary_re = re.compile("^[ -~]{0,200}[!-~]$") - -#: supported http encodings that are also available in python we support -#: for multipart messages. -_supported_multipart_encodings = frozenset(["base64", "quoted-printable"]) - - -def default_stream_factory( - total_content_length, filename, content_type, content_length=None -): - """The stream factory that is used per default.""" - max_size = 1024 * 500 - if SpooledTemporaryFile is not None: - return SpooledTemporaryFile(max_size=max_size, mode="wb+") - if total_content_length is None or total_content_length > max_size: - return TemporaryFile("wb+") - return BytesIO() - - -def parse_form_data( - environ, - stream_factory=None, - charset="utf-8", - errors="replace", - max_form_memory_size=None, - max_content_length=None, - cls=None, - silent=True, -): - """Parse the form data in the environ and return it as tuple in the form - ``(stream, form, files)``. You should only call this method if the - transport method is `POST`, `PUT`, or `PATCH`. - - If the mimetype of the data transmitted is `multipart/form-data` the - files multidict will be filled with `FileStorage` objects. If the - mimetype is unknown the input stream is wrapped and returned as first - argument, else the stream is empty. - - This is a shortcut for the common usage of :class:`FormDataParser`. - - Have a look at :ref:`dealing-with-request-data` for more details. - - .. versionadded:: 0.5 - The `max_form_memory_size`, `max_content_length` and - `cls` parameters were added. - - .. versionadded:: 0.5.1 - The optional `silent` flag was added. - - :param environ: the WSGI environment to be used for parsing. - :param stream_factory: An optional callable that returns a new read and - writeable file descriptor. This callable works - the same as :meth:`~BaseResponse._get_file_stream`. - :param charset: The character set for URL and url encoded form data. - :param errors: The encoding error behavior. - :param max_form_memory_size: the maximum number of bytes to be accepted for - in-memory stored form data. If the data - exceeds the value specified an - :exc:`~exceptions.RequestEntityTooLarge` - exception is raised. - :param max_content_length: If this is provided and the transmitted data - is longer than this value an - :exc:`~exceptions.RequestEntityTooLarge` - exception is raised. - :param cls: an optional dict class to use. If this is not specified - or `None` the default :class:`MultiDict` is used. - :param silent: If set to False parsing errors will not be caught. - :return: A tuple in the form ``(stream, form, files)``. - """ - return FormDataParser( - stream_factory, - charset, - errors, - max_form_memory_size, - max_content_length, - cls, - silent, - ).parse_from_environ(environ) - - -def exhaust_stream(f): - """Helper decorator for methods that exhausts the stream on return.""" - - def wrapper(self, stream, *args, **kwargs): - try: - return f(self, stream, *args, **kwargs) - finally: - exhaust = getattr(stream, "exhaust", None) - if exhaust is not None: - exhaust() - else: - while 1: - chunk = stream.read(1024 * 64) - if not chunk: - break - - return update_wrapper(wrapper, f) - - -class FormDataParser(object): - """This class implements parsing of form data for Werkzeug. By itself - it can parse multipart and url encoded form data. It can be subclassed - and extended but for most mimetypes it is a better idea to use the - untouched stream and expose it as separate attributes on a request - object. - - .. versionadded:: 0.8 - - :param stream_factory: An optional callable that returns a new read and - writeable file descriptor. This callable works - the same as :meth:`~BaseResponse._get_file_stream`. - :param charset: The character set for URL and url encoded form data. - :param errors: The encoding error behavior. - :param max_form_memory_size: the maximum number of bytes to be accepted for - in-memory stored form data. If the data - exceeds the value specified an - :exc:`~exceptions.RequestEntityTooLarge` - exception is raised. - :param max_content_length: If this is provided and the transmitted data - is longer than this value an - :exc:`~exceptions.RequestEntityTooLarge` - exception is raised. - :param cls: an optional dict class to use. If this is not specified - or `None` the default :class:`MultiDict` is used. - :param silent: If set to False parsing errors will not be caught. - """ - - def __init__( - self, - stream_factory=None, - charset="utf-8", - errors="replace", - max_form_memory_size=None, - max_content_length=None, - cls=None, - silent=True, - ): - if stream_factory is None: - stream_factory = default_stream_factory - self.stream_factory = stream_factory - self.charset = charset - self.errors = errors - self.max_form_memory_size = max_form_memory_size - self.max_content_length = max_content_length - if cls is None: - cls = MultiDict - self.cls = cls - self.silent = silent - - def get_parse_func(self, mimetype, options): - return self.parse_functions.get(mimetype) - - def parse_from_environ(self, environ): - """Parses the information from the environment as form data. - - :param environ: the WSGI environment to be used for parsing. - :return: A tuple in the form ``(stream, form, files)``. - """ - content_type = environ.get("CONTENT_TYPE", "") - content_length = get_content_length(environ) - mimetype, options = parse_options_header(content_type) - return self.parse(get_input_stream(environ), mimetype, content_length, options) - - def parse(self, stream, mimetype, content_length, options=None): - """Parses the information from the given stream, mimetype, - content length and mimetype parameters. - - :param stream: an input stream - :param mimetype: the mimetype of the data - :param content_length: the content length of the incoming data - :param options: optional mimetype parameters (used for - the multipart boundary for instance) - :return: A tuple in the form ``(stream, form, files)``. - """ - if ( - self.max_content_length is not None - and content_length is not None - and content_length > self.max_content_length - ): - raise exceptions.RequestEntityTooLarge() - if options is None: - options = {} - - parse_func = self.get_parse_func(mimetype, options) - if parse_func is not None: - try: - return parse_func(self, stream, mimetype, content_length, options) - except ValueError: - if not self.silent: - raise - - return stream, self.cls(), self.cls() - - @exhaust_stream - def _parse_multipart(self, stream, mimetype, content_length, options): - parser = MultiPartParser( - self.stream_factory, - self.charset, - self.errors, - max_form_memory_size=self.max_form_memory_size, - cls=self.cls, - ) - boundary = options.get("boundary") - if boundary is None: - raise ValueError("Missing boundary") - if isinstance(boundary, text_type): - boundary = boundary.encode("ascii") - form, files = parser.parse(stream, boundary, content_length) - return stream, form, files - - @exhaust_stream - def _parse_urlencoded(self, stream, mimetype, content_length, options): - if ( - self.max_form_memory_size is not None - and content_length is not None - and content_length > self.max_form_memory_size - ): - raise exceptions.RequestEntityTooLarge() - form = url_decode_stream(stream, self.charset, errors=self.errors, cls=self.cls) - return stream, form, self.cls() - - #: mapping of mimetypes to parsing functions - parse_functions = { - "multipart/form-data": _parse_multipart, - "application/x-www-form-urlencoded": _parse_urlencoded, - "application/x-url-encoded": _parse_urlencoded, - } - - -def is_valid_multipart_boundary(boundary): - """Checks if the string given is a valid multipart boundary.""" - return _multipart_boundary_re.match(boundary) is not None - - -def _line_parse(line): - """Removes line ending characters and returns a tuple (`stripped_line`, - `is_terminated`). - """ - if line[-2:] in ["\r\n", b"\r\n"]: - return line[:-2], True - elif line[-1:] in ["\r", "\n", b"\r", b"\n"]: - return line[:-1], True - return line, False - - -def parse_multipart_headers(iterable): - """Parses multipart headers from an iterable that yields lines (including - the trailing newline symbol). The iterable has to be newline terminated. - - The iterable will stop at the line where the headers ended so it can be - further consumed. - - :param iterable: iterable of strings that are newline terminated - """ - result = [] - for line in iterable: - line = to_native(line) - line, line_terminated = _line_parse(line) - if not line_terminated: - raise ValueError("unexpected end of line in multipart header") - if not line: - break - elif line[0] in " \t" and result: - key, value = result[-1] - result[-1] = (key, value + "\n " + line[1:]) - else: - parts = line.split(":", 1) - if len(parts) == 2: - result.append((parts[0].strip(), parts[1].strip())) - - # we link the list to the headers, no need to create a copy, the - # list was not shared anyways. - return Headers(result) - - -_begin_form = "begin_form" -_begin_file = "begin_file" -_cont = "cont" -_end = "end" - - -class MultiPartParser(object): - def __init__( - self, - stream_factory=None, - charset="utf-8", - errors="replace", - max_form_memory_size=None, - cls=None, - buffer_size=64 * 1024, - ): - self.charset = charset - self.errors = errors - self.max_form_memory_size = max_form_memory_size - self.stream_factory = ( - default_stream_factory if stream_factory is None else stream_factory - ) - self.cls = MultiDict if cls is None else cls - - # make sure the buffer size is divisible by four so that we can base64 - # decode chunk by chunk - assert buffer_size % 4 == 0, "buffer size has to be divisible by 4" - # also the buffer size has to be at least 1024 bytes long or long headers - # will freak out the system - assert buffer_size >= 1024, "buffer size has to be at least 1KB" - - self.buffer_size = buffer_size - - def _fix_ie_filename(self, filename): - """Internet Explorer 6 transmits the full file name if a file is - uploaded. This function strips the full path if it thinks the - filename is Windows-like absolute. - """ - if filename[1:3] == ":\\" or filename[:2] == "\\\\": - return filename.split("\\")[-1] - return filename - - def _find_terminator(self, iterator): - """The terminator might have some additional newlines before it. - There is at least one application that sends additional newlines - before headers (the python setuptools package). - """ - for line in iterator: - if not line: - break - line = line.strip() - if line: - return line - return b"" - - def fail(self, message): - raise ValueError(message) - - def get_part_encoding(self, headers): - transfer_encoding = headers.get("content-transfer-encoding") - if ( - transfer_encoding is not None - and transfer_encoding in _supported_multipart_encodings - ): - return transfer_encoding - - def get_part_charset(self, headers): - # Figure out input charset for current part - content_type = headers.get("content-type") - if content_type: - mimetype, ct_params = parse_options_header(content_type) - return ct_params.get("charset", self.charset) - return self.charset - - def start_file_streaming(self, filename, headers, total_content_length): - if isinstance(filename, bytes): - filename = filename.decode(self.charset, self.errors) - filename = self._fix_ie_filename(filename) - content_type = headers.get("content-type") - try: - content_length = int(headers["content-length"]) - except (KeyError, ValueError): - content_length = 0 - container = self.stream_factory( - total_content_length=total_content_length, - filename=filename, - content_type=content_type, - content_length=content_length, - ) - return filename, container - - def in_memory_threshold_reached(self, bytes): - raise exceptions.RequestEntityTooLarge() - - def validate_boundary(self, boundary): - if not boundary: - self.fail("Missing boundary") - if not is_valid_multipart_boundary(boundary): - self.fail("Invalid boundary: %s" % boundary) - if len(boundary) > self.buffer_size: # pragma: no cover - # this should never happen because we check for a minimum size - # of 1024 and boundaries may not be longer than 200. The only - # situation when this happens is for non debug builds where - # the assert is skipped. - self.fail("Boundary longer than buffer size") - - def parse_lines(self, file, boundary, content_length, cap_at_buffer=True): - """Generate parts of - ``('begin_form', (headers, name))`` - ``('begin_file', (headers, name, filename))`` - ``('cont', bytestring)`` - ``('end', None)`` - - Always obeys the grammar - parts = ( begin_form cont* end | - begin_file cont* end )* - """ - next_part = b"--" + boundary - last_part = next_part + b"--" - - iterator = chain( - make_line_iter( - file, - limit=content_length, - buffer_size=self.buffer_size, - cap_at_buffer=cap_at_buffer, - ), - _empty_string_iter, - ) - - terminator = self._find_terminator(iterator) - - if terminator == last_part: - return - elif terminator != next_part: - self.fail("Expected boundary at start of multipart data") - - while terminator != last_part: - headers = parse_multipart_headers(iterator) - - disposition = headers.get("content-disposition") - if disposition is None: - self.fail("Missing Content-Disposition header") - disposition, extra = parse_options_header(disposition) - transfer_encoding = self.get_part_encoding(headers) - name = extra.get("name") - filename = extra.get("filename") - - # if no content type is given we stream into memory. A list is - # used as a temporary container. - if filename is None: - yield _begin_form, (headers, name) - - # otherwise we parse the rest of the headers and ask the stream - # factory for something we can write in. - else: - yield _begin_file, (headers, name, filename) - - buf = b"" - for line in iterator: - if not line: - self.fail("unexpected end of stream") - - if line[:2] == b"--": - terminator = line.rstrip() - if terminator in (next_part, last_part): - break - - if transfer_encoding is not None: - if transfer_encoding == "base64": - transfer_encoding = "base64_codec" - try: - line = codecs.decode(line, transfer_encoding) - except Exception: - self.fail("could not decode transfer encoded chunk") - - # we have something in the buffer from the last iteration. - # this is usually a newline delimiter. - if buf: - yield _cont, buf - buf = b"" - - # If the line ends with windows CRLF we write everything except - # the last two bytes. In all other cases however we write - # everything except the last byte. If it was a newline, that's - # fine, otherwise it does not matter because we will write it - # the next iteration. this ensures we do not write the - # final newline into the stream. That way we do not have to - # truncate the stream. However we do have to make sure that - # if something else than a newline is in there we write it - # out. - if line[-2:] == b"\r\n": - buf = b"\r\n" - cutoff = -2 - else: - buf = line[-1:] - cutoff = -1 - yield _cont, line[:cutoff] - - else: # pragma: no cover - raise ValueError("unexpected end of part") - - # if we have a leftover in the buffer that is not a newline - # character we have to flush it, otherwise we will chop of - # certain values. - if buf not in (b"", b"\r", b"\n", b"\r\n"): - yield _cont, buf - - yield _end, None - - def parse_parts(self, file, boundary, content_length): - """Generate ``('file', (name, val))`` and - ``('form', (name, val))`` parts. - """ - in_memory = 0 - - for ellt, ell in self.parse_lines(file, boundary, content_length): - if ellt == _begin_file: - headers, name, filename = ell - is_file = True - guard_memory = False - filename, container = self.start_file_streaming( - filename, headers, content_length - ) - _write = container.write - - elif ellt == _begin_form: - headers, name = ell - is_file = False - container = [] - _write = container.append - guard_memory = self.max_form_memory_size is not None - - elif ellt == _cont: - _write(ell) - # if we write into memory and there is a memory size limit we - # count the number of bytes in memory and raise an exception if - # there is too much data in memory. - if guard_memory: - in_memory += len(ell) - if in_memory > self.max_form_memory_size: - self.in_memory_threshold_reached(in_memory) - - elif ellt == _end: - if is_file: - container.seek(0) - yield ( - "file", - (name, FileStorage(container, filename, name, headers=headers)), - ) - else: - part_charset = self.get_part_charset(headers) - yield ( - "form", - (name, b"".join(container).decode(part_charset, self.errors)), - ) - - def parse(self, file, boundary, content_length): - formstream, filestream = tee( - self.parse_parts(file, boundary, content_length), 2 - ) - form = (p[1] for p in formstream if p[0] == "form") - files = (p[1] for p in filestream if p[0] == "file") - return self.cls(form), self.cls(files) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/http.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/http.py deleted file mode 100644 index c33293a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/http.py +++ /dev/null @@ -1,1307 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.http - ~~~~~~~~~~~~~ - - Werkzeug comes with a bunch of utilities that help Werkzeug to deal with - HTTP data. Most of the classes and functions provided by this module are - used by the wrappers, but they are useful on their own, too, especially if - the response and request objects are not used. - - This covers some of the more HTTP centric features of WSGI, some other - utilities such as cookie handling are documented in the `werkzeug.utils` - module. - - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import base64 -import re -import warnings -from datetime import datetime -from datetime import timedelta -from hashlib import md5 -from time import gmtime -from time import time - -from ._compat import integer_types -from ._compat import iteritems -from ._compat import PY2 -from ._compat import string_types -from ._compat import text_type -from ._compat import to_bytes -from ._compat import to_unicode -from ._compat import try_coerce_native -from ._internal import _cookie_parse_impl -from ._internal import _cookie_quote -from ._internal import _make_cookie_domain - -try: - from email.utils import parsedate_tz -except ImportError: - from email.Utils import parsedate_tz - -try: - from urllib.request import parse_http_list as _parse_list_header - from urllib.parse import unquote_to_bytes as _unquote -except ImportError: - from urllib2 import parse_http_list as _parse_list_header - from urllib2 import unquote as _unquote - -_cookie_charset = "latin1" -_basic_auth_charset = "utf-8" -# for explanation of "media-range", etc. see Sections 5.3.{1,2} of RFC 7231 -_accept_re = re.compile( - r""" - ( # media-range capturing-parenthesis - [^\s;,]+ # type/subtype - (?:[ \t]*;[ \t]* # ";" - (?: # parameter non-capturing-parenthesis - [^\s;,q][^\s;,]* # token that doesn't start with "q" - | # or - q[^\s;,=][^\s;,]* # token that is more than just "q" - ) - )* # zero or more parameters - ) # end of media-range - (?:[ \t]*;[ \t]*q= # weight is a "q" parameter - (\d*(?:\.\d+)?) # qvalue capturing-parentheses - [^,]* # "extension" accept params: who cares? - )? # accept params are optional - """, - re.VERBOSE, -) -_token_chars = frozenset( - "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~" -) -_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') -_unsafe_header_chars = set('()<>@,;:"/[]?={} \t') -_option_header_piece_re = re.compile( - r""" - ;\s*,?\s* # newlines were replaced with commas - (?P - "[^"\\]*(?:\\.[^"\\]*)*" # quoted string - | - [^\s;,=*]+ # token - ) - (?:\*(?P\d+))? # *1, optional continuation index - \s* - (?: # optionally followed by =value - (?: # equals sign, possibly with encoding - \*\s*=\s* # * indicates extended notation - (?: # optional encoding - (?P[^\s]+?) - '(?P[^\s]*?)' - )? - | - =\s* # basic notation - ) - (?P - "[^"\\]*(?:\\.[^"\\]*)*" # quoted string - | - [^;,]+ # token - )? - )? - \s* - """, - flags=re.VERBOSE, -) -_option_header_start_mime_type = re.compile(r",\s*([^;,\s]+)([;,]\s*.+)?") - -_entity_headers = frozenset( - [ - "allow", - "content-encoding", - "content-language", - "content-length", - "content-location", - "content-md5", - "content-range", - "content-type", - "expires", - "last-modified", - ] -) -_hop_by_hop_headers = frozenset( - [ - "connection", - "keep-alive", - "proxy-authenticate", - "proxy-authorization", - "te", - "trailer", - "transfer-encoding", - "upgrade", - ] -) - - -HTTP_STATUS_CODES = { - 100: "Continue", - 101: "Switching Protocols", - 102: "Processing", - 103: "Early Hints", # see RFC 8297 - 200: "OK", - 201: "Created", - 202: "Accepted", - 203: "Non Authoritative Information", - 204: "No Content", - 205: "Reset Content", - 206: "Partial Content", - 207: "Multi Status", - 208: "Already Reported", # see RFC 5842 - 226: "IM Used", # see RFC 3229 - 300: "Multiple Choices", - 301: "Moved Permanently", - 302: "Found", - 303: "See Other", - 304: "Not Modified", - 305: "Use Proxy", - 306: "Switch Proxy", # unused - 307: "Temporary Redirect", - 308: "Permanent Redirect", - 400: "Bad Request", - 401: "Unauthorized", - 402: "Payment Required", # unused - 403: "Forbidden", - 404: "Not Found", - 405: "Method Not Allowed", - 406: "Not Acceptable", - 407: "Proxy Authentication Required", - 408: "Request Timeout", - 409: "Conflict", - 410: "Gone", - 411: "Length Required", - 412: "Precondition Failed", - 413: "Request Entity Too Large", - 414: "Request URI Too Long", - 415: "Unsupported Media Type", - 416: "Requested Range Not Satisfiable", - 417: "Expectation Failed", - 418: "I'm a teapot", # see RFC 2324 - 421: "Misdirected Request", # see RFC 7540 - 422: "Unprocessable Entity", - 423: "Locked", - 424: "Failed Dependency", - 425: "Too Early", # see RFC 8470 - 426: "Upgrade Required", - 428: "Precondition Required", # see RFC 6585 - 429: "Too Many Requests", - 431: "Request Header Fields Too Large", - 449: "Retry With", # proprietary MS extension - 451: "Unavailable For Legal Reasons", - 500: "Internal Server Error", - 501: "Not Implemented", - 502: "Bad Gateway", - 503: "Service Unavailable", - 504: "Gateway Timeout", - 505: "HTTP Version Not Supported", - 506: "Variant Also Negotiates", # see RFC 2295 - 507: "Insufficient Storage", - 508: "Loop Detected", # see RFC 5842 - 510: "Not Extended", - 511: "Network Authentication Failed", # see RFC 6585 -} - - -def wsgi_to_bytes(data): - """coerce wsgi unicode represented bytes to real ones""" - if isinstance(data, bytes): - return data - return data.encode("latin1") # XXX: utf8 fallback? - - -def bytes_to_wsgi(data): - assert isinstance(data, bytes), "data must be bytes" - if isinstance(data, str): - return data - else: - return data.decode("latin1") - - -def quote_header_value(value, extra_chars="", allow_token=True): - """Quote a header value if necessary. - - .. versionadded:: 0.5 - - :param value: the value to quote. - :param extra_chars: a list of extra characters to skip quoting. - :param allow_token: if this is enabled token values are returned - unchanged. - """ - if isinstance(value, bytes): - value = bytes_to_wsgi(value) - value = str(value) - if allow_token: - token_chars = _token_chars | set(extra_chars) - if set(value).issubset(token_chars): - return value - return '"%s"' % value.replace("\\", "\\\\").replace('"', '\\"') - - -def unquote_header_value(value, is_filename=False): - r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). - This does not use the real unquoting but what browsers are actually - using for quoting. - - .. versionadded:: 0.5 - - :param value: the header value to unquote. - """ - if value and value[0] == value[-1] == '"': - # this is not the real unquoting, but fixing this so that the - # RFC is met will result in bugs with internet explorer and - # probably some other browsers as well. IE for example is - # uploading files with "C:\foo\bar.txt" as filename - value = value[1:-1] - - # if this is a filename and the starting characters look like - # a UNC path, then just return the value without quotes. Using the - # replace sequence below on a UNC path has the effect of turning - # the leading double slash into a single slash and then - # _fix_ie_filename() doesn't work correctly. See #458. - if not is_filename or value[:2] != "\\\\": - return value.replace("\\\\", "\\").replace('\\"', '"') - return value - - -def dump_options_header(header, options): - """The reverse function to :func:`parse_options_header`. - - :param header: the header to dump - :param options: a dict of options to append. - """ - segments = [] - if header is not None: - segments.append(header) - for key, value in iteritems(options): - if value is None: - segments.append(key) - else: - segments.append("%s=%s" % (key, quote_header_value(value))) - return "; ".join(segments) - - -def dump_header(iterable, allow_token=True): - """Dump an HTTP header again. This is the reversal of - :func:`parse_list_header`, :func:`parse_set_header` and - :func:`parse_dict_header`. This also quotes strings that include an - equals sign unless you pass it as dict of key, value pairs. - - >>> dump_header({'foo': 'bar baz'}) - 'foo="bar baz"' - >>> dump_header(('foo', 'bar baz')) - 'foo, "bar baz"' - - :param iterable: the iterable or dict of values to quote. - :param allow_token: if set to `False` tokens as values are disallowed. - See :func:`quote_header_value` for more details. - """ - if isinstance(iterable, dict): - items = [] - for key, value in iteritems(iterable): - if value is None: - items.append(key) - else: - items.append( - "%s=%s" % (key, quote_header_value(value, allow_token=allow_token)) - ) - else: - items = [quote_header_value(x, allow_token=allow_token) for x in iterable] - return ", ".join(items) - - -def dump_csp_header(header): - """Dump a Content Security Policy header. - - These are structured into policies such as "default-src 'self'; - script-src 'self'". - - .. versionadded:: 1.0.0 - Support for Content Security Policy headers was added. - - """ - return "; ".join("%s %s" % (key, value) for key, value in iteritems(header)) - - -def parse_list_header(value): - """Parse lists as described by RFC 2068 Section 2. - - In particular, parse comma-separated lists where the elements of - the list may include quoted-strings. A quoted-string could - contain a comma. A non-quoted string could have quotes in the - middle. Quotes are removed automatically after parsing. - - It basically works like :func:`parse_set_header` just that items - may appear multiple times and case sensitivity is preserved. - - The return value is a standard :class:`list`: - - >>> parse_list_header('token, "quoted value"') - ['token', 'quoted value'] - - To create a header from the :class:`list` again, use the - :func:`dump_header` function. - - :param value: a string with a list header. - :return: :class:`list` - """ - result = [] - for item in _parse_list_header(value): - if item[:1] == item[-1:] == '"': - item = unquote_header_value(item[1:-1]) - result.append(item) - return result - - -def parse_dict_header(value, cls=dict): - """Parse lists of key, value pairs as described by RFC 2068 Section 2 and - convert them into a python dict (or any other mapping object created from - the type with a dict like interface provided by the `cls` argument): - - >>> d = parse_dict_header('foo="is a fish", bar="as well"') - >>> type(d) is dict - True - >>> sorted(d.items()) - [('bar', 'as well'), ('foo', 'is a fish')] - - If there is no value for a key it will be `None`: - - >>> parse_dict_header('key_without_value') - {'key_without_value': None} - - To create a header from the :class:`dict` again, use the - :func:`dump_header` function. - - .. versionchanged:: 0.9 - Added support for `cls` argument. - - :param value: a string with a dict header. - :param cls: callable to use for storage of parsed results. - :return: an instance of `cls` - """ - result = cls() - if not isinstance(value, text_type): - # XXX: validate - value = bytes_to_wsgi(value) - for item in _parse_list_header(value): - if "=" not in item: - result[item] = None - continue - name, value = item.split("=", 1) - if value[:1] == value[-1:] == '"': - value = unquote_header_value(value[1:-1]) - result[name] = value - return result - - -def parse_options_header(value, multiple=False): - """Parse a ``Content-Type`` like header into a tuple with the content - type and the options: - - >>> parse_options_header('text/html; charset=utf8') - ('text/html', {'charset': 'utf8'}) - - This should not be used to parse ``Cache-Control`` like headers that use - a slightly different format. For these headers use the - :func:`parse_dict_header` function. - - .. versionchanged:: 0.15 - :rfc:`2231` parameter continuations are handled. - - .. versionadded:: 0.5 - - :param value: the header to parse. - :param multiple: Whether try to parse and return multiple MIME types - :return: (mimetype, options) or (mimetype, options, mimetype, options, …) - if multiple=True - """ - if not value: - return "", {} - - result = [] - - value = "," + value.replace("\n", ",") - while value: - match = _option_header_start_mime_type.match(value) - if not match: - break - result.append(match.group(1)) # mimetype - options = {} - # Parse options - rest = match.group(2) - continued_encoding = None - while rest: - optmatch = _option_header_piece_re.match(rest) - if not optmatch: - break - option, count, encoding, language, option_value = optmatch.groups() - # Continuations don't have to supply the encoding after the - # first line. If we're in a continuation, track the current - # encoding to use for subsequent lines. Reset it when the - # continuation ends. - if not count: - continued_encoding = None - else: - if not encoding: - encoding = continued_encoding - continued_encoding = encoding - option = unquote_header_value(option) - if option_value is not None: - option_value = unquote_header_value(option_value, option == "filename") - if encoding is not None: - option_value = _unquote(option_value).decode(encoding) - if count: - # Continuations append to the existing value. For - # simplicity, this ignores the possibility of - # out-of-order indices, which shouldn't happen anyway. - options[option] = options.get(option, "") + option_value - else: - options[option] = option_value - rest = rest[optmatch.end() :] - result.append(options) - if multiple is False: - return tuple(result) - value = rest - - return tuple(result) if result else ("", {}) - - -def parse_accept_header(value, cls=None): - """Parses an HTTP Accept-* header. This does not implement a complete - valid algorithm but one that supports at least value and quality - extraction. - - Returns a new :class:`Accept` object (basically a list of ``(value, quality)`` - tuples sorted by the quality with some additional accessor methods). - - The second parameter can be a subclass of :class:`Accept` that is created - with the parsed values and returned. - - :param value: the accept header string to be parsed. - :param cls: the wrapper class for the return value (can be - :class:`Accept` or a subclass thereof) - :return: an instance of `cls`. - """ - if cls is None: - cls = Accept - - if not value: - return cls(None) - - result = [] - for match in _accept_re.finditer(value): - quality = match.group(2) - if not quality: - quality = 1 - else: - quality = max(min(float(quality), 1), 0) - result.append((match.group(1), quality)) - return cls(result) - - -def parse_cache_control_header(value, on_update=None, cls=None): - """Parse a cache control header. The RFC differs between response and - request cache control, this method does not. It's your responsibility - to not use the wrong control statements. - - .. versionadded:: 0.5 - The `cls` was added. If not specified an immutable - :class:`~werkzeug.datastructures.RequestCacheControl` is returned. - - :param value: a cache control header to be parsed. - :param on_update: an optional callable that is called every time a value - on the :class:`~werkzeug.datastructures.CacheControl` - object is changed. - :param cls: the class for the returned object. By default - :class:`~werkzeug.datastructures.RequestCacheControl` is used. - :return: a `cls` object. - """ - if cls is None: - cls = RequestCacheControl - if not value: - return cls(None, on_update) - return cls(parse_dict_header(value), on_update) - - -def parse_csp_header(value, on_update=None, cls=None): - """Parse a Content Security Policy header. - - .. versionadded:: 1.0.0 - Support for Content Security Policy headers was added. - - :param value: a csp header to be parsed. - :param on_update: an optional callable that is called every time a value - on the object is changed. - :param cls: the class for the returned object. By default - :class:`~werkzeug.datastructures.ContentSecurityPolicy` is used. - :return: a `cls` object. - """ - - if cls is None: - cls = ContentSecurityPolicy - if value is None: - return cls(None, on_update) - items = [] - for policy in value.split(";"): - policy = policy.strip() - # Ignore badly formatted policies (no space) - if " " in policy: - directive, value = policy.strip().split(" ", 1) - items.append((directive.strip(), value.strip())) - return cls(items, on_update) - - -def parse_set_header(value, on_update=None): - """Parse a set-like header and return a - :class:`~werkzeug.datastructures.HeaderSet` object: - - >>> hs = parse_set_header('token, "quoted value"') - - The return value is an object that treats the items case-insensitively - and keeps the order of the items: - - >>> 'TOKEN' in hs - True - >>> hs.index('quoted value') - 1 - >>> hs - HeaderSet(['token', 'quoted value']) - - To create a header from the :class:`HeaderSet` again, use the - :func:`dump_header` function. - - :param value: a set header to be parsed. - :param on_update: an optional callable that is called every time a - value on the :class:`~werkzeug.datastructures.HeaderSet` - object is changed. - :return: a :class:`~werkzeug.datastructures.HeaderSet` - """ - if not value: - return HeaderSet(None, on_update) - return HeaderSet(parse_list_header(value), on_update) - - -def parse_authorization_header(value): - """Parse an HTTP basic/digest authorization header transmitted by the web - browser. The return value is either `None` if the header was invalid or - not given, otherwise an :class:`~werkzeug.datastructures.Authorization` - object. - - :param value: the authorization header to parse. - :return: a :class:`~werkzeug.datastructures.Authorization` object or `None`. - """ - if not value: - return - value = wsgi_to_bytes(value) - try: - auth_type, auth_info = value.split(None, 1) - auth_type = auth_type.lower() - except ValueError: - return - if auth_type == b"basic": - try: - username, password = base64.b64decode(auth_info).split(b":", 1) - except Exception: - return - return Authorization( - "basic", - { - "username": to_unicode(username, _basic_auth_charset), - "password": to_unicode(password, _basic_auth_charset), - }, - ) - elif auth_type == b"digest": - auth_map = parse_dict_header(auth_info) - for key in "username", "realm", "nonce", "uri", "response": - if key not in auth_map: - return - if "qop" in auth_map: - if not auth_map.get("nc") or not auth_map.get("cnonce"): - return - return Authorization("digest", auth_map) - - -def parse_www_authenticate_header(value, on_update=None): - """Parse an HTTP WWW-Authenticate header into a - :class:`~werkzeug.datastructures.WWWAuthenticate` object. - - :param value: a WWW-Authenticate header to parse. - :param on_update: an optional callable that is called every time a value - on the :class:`~werkzeug.datastructures.WWWAuthenticate` - object is changed. - :return: a :class:`~werkzeug.datastructures.WWWAuthenticate` object. - """ - if not value: - return WWWAuthenticate(on_update=on_update) - try: - auth_type, auth_info = value.split(None, 1) - auth_type = auth_type.lower() - except (ValueError, AttributeError): - return WWWAuthenticate(value.strip().lower(), on_update=on_update) - return WWWAuthenticate(auth_type, parse_dict_header(auth_info), on_update) - - -def parse_if_range_header(value): - """Parses an if-range header which can be an etag or a date. Returns - a :class:`~werkzeug.datastructures.IfRange` object. - - .. versionadded:: 0.7 - """ - if not value: - return IfRange() - date = parse_date(value) - if date is not None: - return IfRange(date=date) - # drop weakness information - return IfRange(unquote_etag(value)[0]) - - -def parse_range_header(value, make_inclusive=True): - """Parses a range header into a :class:`~werkzeug.datastructures.Range` - object. If the header is missing or malformed `None` is returned. - `ranges` is a list of ``(start, stop)`` tuples where the ranges are - non-inclusive. - - .. versionadded:: 0.7 - """ - if not value or "=" not in value: - return None - - ranges = [] - last_end = 0 - units, rng = value.split("=", 1) - units = units.strip().lower() - - for item in rng.split(","): - item = item.strip() - if "-" not in item: - return None - if item.startswith("-"): - if last_end < 0: - return None - try: - begin = int(item) - except ValueError: - return None - end = None - last_end = -1 - elif "-" in item: - begin, end = item.split("-", 1) - begin = begin.strip() - end = end.strip() - if not begin.isdigit(): - return None - begin = int(begin) - if begin < last_end or last_end < 0: - return None - if end: - if not end.isdigit(): - return None - end = int(end) + 1 - if begin >= end: - return None - else: - end = None - last_end = end - ranges.append((begin, end)) - - return Range(units, ranges) - - -def parse_content_range_header(value, on_update=None): - """Parses a range header into a - :class:`~werkzeug.datastructures.ContentRange` object or `None` if - parsing is not possible. - - .. versionadded:: 0.7 - - :param value: a content range header to be parsed. - :param on_update: an optional callable that is called every time a value - on the :class:`~werkzeug.datastructures.ContentRange` - object is changed. - """ - if value is None: - return None - try: - units, rangedef = (value or "").strip().split(None, 1) - except ValueError: - return None - - if "/" not in rangedef: - return None - rng, length = rangedef.split("/", 1) - if length == "*": - length = None - elif length.isdigit(): - length = int(length) - else: - return None - - if rng == "*": - return ContentRange(units, None, None, length, on_update=on_update) - elif "-" not in rng: - return None - - start, stop = rng.split("-", 1) - try: - start = int(start) - stop = int(stop) + 1 - except ValueError: - return None - - if is_byte_range_valid(start, stop, length): - return ContentRange(units, start, stop, length, on_update=on_update) - - -def quote_etag(etag, weak=False): - """Quote an etag. - - :param etag: the etag to quote. - :param weak: set to `True` to tag it "weak". - """ - if '"' in etag: - raise ValueError("invalid etag") - etag = '"%s"' % etag - if weak: - etag = "W/" + etag - return etag - - -def unquote_etag(etag): - """Unquote a single etag: - - >>> unquote_etag('W/"bar"') - ('bar', True) - >>> unquote_etag('"bar"') - ('bar', False) - - :param etag: the etag identifier to unquote. - :return: a ``(etag, weak)`` tuple. - """ - if not etag: - return None, None - etag = etag.strip() - weak = False - if etag.startswith(("W/", "w/")): - weak = True - etag = etag[2:] - if etag[:1] == etag[-1:] == '"': - etag = etag[1:-1] - return etag, weak - - -def parse_etags(value): - """Parse an etag header. - - :param value: the tag header to parse - :return: an :class:`~werkzeug.datastructures.ETags` object. - """ - if not value: - return ETags() - strong = [] - weak = [] - end = len(value) - pos = 0 - while pos < end: - match = _etag_re.match(value, pos) - if match is None: - break - is_weak, quoted, raw = match.groups() - if raw == "*": - return ETags(star_tag=True) - elif quoted: - raw = quoted - if is_weak: - weak.append(raw) - else: - strong.append(raw) - pos = match.end() - return ETags(strong, weak) - - -def generate_etag(data): - """Generate an etag for some data.""" - return md5(data).hexdigest() - - -def parse_date(value): - """Parse one of the following date formats into a datetime object: - - .. sourcecode:: text - - Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 - Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 - Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format - - If parsing fails the return value is `None`. - - :param value: a string with a supported date format. - :return: a :class:`datetime.datetime` object. - """ - if value: - t = parsedate_tz(value.strip()) - if t is not None: - try: - year = t[0] - # unfortunately that function does not tell us if two digit - # years were part of the string, or if they were prefixed - # with two zeroes. So what we do is to assume that 69-99 - # refer to 1900, and everything below to 2000 - if year >= 0 and year <= 68: - year += 2000 - elif year >= 69 and year <= 99: - year += 1900 - return datetime(*((year,) + t[1:7])) - timedelta(seconds=t[-1] or 0) - except (ValueError, OverflowError): - return None - - -def _dump_date(d, delim): - """Used for `http_date` and `cookie_date`.""" - if d is None: - d = gmtime() - elif isinstance(d, datetime): - d = d.utctimetuple() - elif isinstance(d, (integer_types, float)): - d = gmtime(d) - return "%s, %02d%s%s%s%04d %02d:%02d:%02d GMT" % ( - ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")[d.tm_wday], - d.tm_mday, - delim, - ( - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - )[d.tm_mon - 1], - delim, - d.tm_year, - d.tm_hour, - d.tm_min, - d.tm_sec, - ) - - -def cookie_date(expires=None): - """Formats the time to ensure compatibility with Netscape's cookie - standard. - - Accepts a floating point number expressed in seconds since the epoch in, a - datetime object or a timetuple. All times in UTC. The :func:`parse_date` - function can be used to parse such a date. - - Outputs a string in the format ``Wdy, DD-Mon-YYYY HH:MM:SS GMT``. - - :param expires: If provided that date is used, otherwise the current. - """ - return _dump_date(expires, "-") - - -def http_date(timestamp=None): - """Formats the time to match the RFC1123 date format. - - Accepts a floating point number expressed in seconds since the epoch in, a - datetime object or a timetuple. All times in UTC. The :func:`parse_date` - function can be used to parse such a date. - - Outputs a string in the format ``Wdy, DD Mon YYYY HH:MM:SS GMT``. - - :param timestamp: If provided that date is used, otherwise the current. - """ - return _dump_date(timestamp, " ") - - -def parse_age(value=None): - """Parses a base-10 integer count of seconds into a timedelta. - - If parsing fails, the return value is `None`. - - :param value: a string consisting of an integer represented in base-10 - :return: a :class:`datetime.timedelta` object or `None`. - """ - if not value: - return None - try: - seconds = int(value) - except ValueError: - return None - if seconds < 0: - return None - try: - return timedelta(seconds=seconds) - except OverflowError: - return None - - -def dump_age(age=None): - """Formats the duration as a base-10 integer. - - :param age: should be an integer number of seconds, - a :class:`datetime.timedelta` object, or, - if the age is unknown, `None` (default). - """ - if age is None: - return - if isinstance(age, timedelta): - # do the equivalent of Python 2.7's timedelta.total_seconds(), - # but disregarding fractional seconds - age = age.seconds + (age.days * 24 * 3600) - - age = int(age) - if age < 0: - raise ValueError("age cannot be negative") - - return str(age) - - -def is_resource_modified( - environ, etag=None, data=None, last_modified=None, ignore_if_range=True -): - """Convenience method for conditional requests. - - :param environ: the WSGI environment of the request to be checked. - :param etag: the etag for the response for comparison. - :param data: or alternatively the data of the response to automatically - generate an etag using :func:`generate_etag`. - :param last_modified: an optional date of the last modification. - :param ignore_if_range: If `False`, `If-Range` header will be taken into - account. - :return: `True` if the resource was modified, otherwise `False`. - - .. versionchanged:: 1.0.0 - The check is run for methods other than ``GET`` and ``HEAD``. - """ - if etag is None and data is not None: - etag = generate_etag(data) - elif data is not None: - raise TypeError("both data and etag given") - - unmodified = False - if isinstance(last_modified, string_types): - last_modified = parse_date(last_modified) - - # ensure that microsecond is zero because the HTTP spec does not transmit - # that either and we might have some false positives. See issue #39 - if last_modified is not None: - last_modified = last_modified.replace(microsecond=0) - - if_range = None - if not ignore_if_range and "HTTP_RANGE" in environ: - # https://tools.ietf.org/html/rfc7233#section-3.2 - # A server MUST ignore an If-Range header field received in a request - # that does not contain a Range header field. - if_range = parse_if_range_header(environ.get("HTTP_IF_RANGE")) - - if if_range is not None and if_range.date is not None: - modified_since = if_range.date - else: - modified_since = parse_date(environ.get("HTTP_IF_MODIFIED_SINCE")) - - if modified_since and last_modified and last_modified <= modified_since: - unmodified = True - - if etag: - etag, _ = unquote_etag(etag) - if if_range is not None and if_range.etag is not None: - unmodified = parse_etags(if_range.etag).contains(etag) - else: - if_none_match = parse_etags(environ.get("HTTP_IF_NONE_MATCH")) - if if_none_match: - # https://tools.ietf.org/html/rfc7232#section-3.2 - # "A recipient MUST use the weak comparison function when comparing - # entity-tags for If-None-Match" - unmodified = if_none_match.contains_weak(etag) - - # https://tools.ietf.org/html/rfc7232#section-3.1 - # "Origin server MUST use the strong comparison function when - # comparing entity-tags for If-Match" - if_match = parse_etags(environ.get("HTTP_IF_MATCH")) - if if_match: - unmodified = not if_match.is_strong(etag) - - return not unmodified - - -def remove_entity_headers(headers, allowed=("expires", "content-location")): - """Remove all entity headers from a list or :class:`Headers` object. This - operation works in-place. `Expires` and `Content-Location` headers are - by default not removed. The reason for this is :rfc:`2616` section - 10.3.5 which specifies some entity headers that should be sent. - - .. versionchanged:: 0.5 - added `allowed` parameter. - - :param headers: a list or :class:`Headers` object. - :param allowed: a list of headers that should still be allowed even though - they are entity headers. - """ - allowed = set(x.lower() for x in allowed) - headers[:] = [ - (key, value) - for key, value in headers - if not is_entity_header(key) or key.lower() in allowed - ] - - -def remove_hop_by_hop_headers(headers): - """Remove all HTTP/1.1 "Hop-by-Hop" headers from a list or - :class:`Headers` object. This operation works in-place. - - .. versionadded:: 0.5 - - :param headers: a list or :class:`Headers` object. - """ - headers[:] = [ - (key, value) for key, value in headers if not is_hop_by_hop_header(key) - ] - - -def is_entity_header(header): - """Check if a header is an entity header. - - .. versionadded:: 0.5 - - :param header: the header to test. - :return: `True` if it's an entity header, `False` otherwise. - """ - return header.lower() in _entity_headers - - -def is_hop_by_hop_header(header): - """Check if a header is an HTTP/1.1 "Hop-by-Hop" header. - - .. versionadded:: 0.5 - - :param header: the header to test. - :return: `True` if it's an HTTP/1.1 "Hop-by-Hop" header, `False` otherwise. - """ - return header.lower() in _hop_by_hop_headers - - -def parse_cookie(header, charset="utf-8", errors="replace", cls=None): - """Parse a cookie from a string or WSGI environ. - - The same key can be provided multiple times, the values are stored - in-order. The default :class:`MultiDict` will have the first value - first, and all values can be retrieved with - :meth:`MultiDict.getlist`. - - :param header: The cookie header as a string, or a WSGI environ dict - with a ``HTTP_COOKIE`` key. - :param charset: The charset for the cookie values. - :param errors: The error behavior for the charset decoding. - :param cls: A dict-like class to store the parsed cookies in. - Defaults to :class:`MultiDict`. - - .. versionchanged:: 1.0.0 - Returns a :class:`MultiDict` instead of a - ``TypeConversionDict``. - - .. versionchanged:: 0.5 - Returns a :class:`TypeConversionDict` instead of a regular dict. - The ``cls`` parameter was added. - """ - if isinstance(header, dict): - header = header.get("HTTP_COOKIE", "") - elif header is None: - header = "" - - # On Python 3, PEP 3333 sends headers through the environ as latin1 - # decoded strings. Encode strings back to bytes for parsing. - if isinstance(header, text_type): - header = header.encode("latin1", "replace") - - if cls is None: - cls = MultiDict - - def _parse_pairs(): - for key, val in _cookie_parse_impl(header): - key = to_unicode(key, charset, errors, allow_none_charset=True) - if not key: - continue - val = to_unicode(val, charset, errors, allow_none_charset=True) - yield try_coerce_native(key), val - - return cls(_parse_pairs()) - - -def dump_cookie( - key, - value="", - max_age=None, - expires=None, - path="/", - domain=None, - secure=False, - httponly=False, - charset="utf-8", - sync_expires=True, - max_size=4093, - samesite=None, -): - """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix - The parameters are the same as in the cookie Morsel object in the - Python standard library but it accepts unicode data, too. - - On Python 3 the return value of this function will be a unicode - string, on Python 2 it will be a native string. In both cases the - return value is usually restricted to ascii as the vast majority of - values are properly escaped, but that is no guarantee. If a unicode - string is returned it's tunneled through latin1 as required by - PEP 3333. - - The return value is not ASCII safe if the key contains unicode - characters. This is technically against the specification but - happens in the wild. It's strongly recommended to not use - non-ASCII values for the keys. - - :param max_age: should be a number of seconds, or `None` (default) if - the cookie should last only as long as the client's - browser session. Additionally `timedelta` objects - are accepted, too. - :param expires: should be a `datetime` object or unix timestamp. - :param path: limits the cookie to a given path, per default it will - span the whole domain. - :param domain: Use this if you want to set a cross-domain cookie. For - example, ``domain=".example.com"`` will set a cookie - that is readable by the domain ``www.example.com``, - ``foo.example.com`` etc. Otherwise, a cookie will only - be readable by the domain that set it. - :param secure: The cookie will only be available via HTTPS - :param httponly: disallow JavaScript to access the cookie. This is an - extension to the cookie standard and probably not - supported by all browsers. - :param charset: the encoding for unicode values. - :param sync_expires: automatically set expires if max_age is defined - but expires not. - :param max_size: Warn if the final header value exceeds this size. The - default, 4093, should be safely `supported by most browsers - `_. Set to 0 to disable this check. - :param samesite: Limits the scope of the cookie such that it will - only be attached to requests if those requests are same-site. - - .. _`cookie`: http://browsercookielimits.squawky.net/ - - .. versionchanged:: 1.0.0 - The string ``'None'`` is accepted for ``samesite``. - """ - key = to_bytes(key, charset) - value = to_bytes(value, charset) - - if path is not None: - from .urls import iri_to_uri - - path = iri_to_uri(path, charset) - domain = _make_cookie_domain(domain) - if isinstance(max_age, timedelta): - max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds - if expires is not None: - if not isinstance(expires, string_types): - expires = cookie_date(expires) - elif max_age is not None and sync_expires: - expires = to_bytes(cookie_date(time() + max_age)) - - if samesite is not None: - samesite = samesite.title() - - if samesite not in {"Strict", "Lax", "None"}: - raise ValueError("SameSite must be 'Strict', 'Lax', or 'None'.") - - buf = [key + b"=" + _cookie_quote(value)] - - # XXX: In theory all of these parameters that are not marked with `None` - # should be quoted. Because stdlib did not quote it before I did not - # want to introduce quoting there now. - for k, v, q in ( - (b"Domain", domain, True), - (b"Expires", expires, False), - (b"Max-Age", max_age, False), - (b"Secure", secure, None), - (b"HttpOnly", httponly, None), - (b"Path", path, False), - (b"SameSite", samesite, False), - ): - if q is None: - if v: - buf.append(k) - continue - - if v is None: - continue - - tmp = bytearray(k) - if not isinstance(v, (bytes, bytearray)): - v = to_bytes(text_type(v), charset) - if q: - v = _cookie_quote(v) - tmp += b"=" + v - buf.append(bytes(tmp)) - - # The return value will be an incorrectly encoded latin1 header on - # Python 3 for consistency with the headers object and a bytestring - # on Python 2 because that's how the API makes more sense. - rv = b"; ".join(buf) - if not PY2: - rv = rv.decode("latin1") - - # Warn if the final value of the cookie is larger than the limit. If the - # cookie is too large, then it may be silently ignored by the browser, - # which can be quite hard to debug. - cookie_size = len(rv) - - if max_size and cookie_size > max_size: - value_size = len(value) - warnings.warn( - 'The "{key}" cookie is too large: the value was {value_size} bytes' - " but the header required {extra_size} extra bytes. The final size" - " was {cookie_size} bytes but the limit is {max_size} bytes." - " Browsers may silently ignore cookies larger than this.".format( - key=key, - value_size=value_size, - extra_size=cookie_size - value_size, - cookie_size=cookie_size, - max_size=max_size, - ), - stacklevel=2, - ) - - return rv - - -def is_byte_range_valid(start, stop, length): - """Checks if a given byte content range is valid for the given length. - - .. versionadded:: 0.7 - """ - if (start is None) != (stop is None): - return False - elif start is None: - return length is None or length >= 0 - elif length is None: - return 0 <= start < stop - elif start >= stop: - return False - return 0 <= start < length - - -# circular dependencies -from .datastructures import Accept -from .datastructures import Authorization -from .datastructures import ContentRange -from .datastructures import ContentSecurityPolicy -from .datastructures import ETags -from .datastructures import HeaderSet -from .datastructures import IfRange -from .datastructures import MultiDict -from .datastructures import Range -from .datastructures import RequestCacheControl -from .datastructures import WWWAuthenticate diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/local.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/local.py deleted file mode 100644 index 626b87b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/local.py +++ /dev/null @@ -1,420 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.local - ~~~~~~~~~~~~~~ - - This module implements context-local objects. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import copy -from functools import update_wrapper - -from ._compat import implements_bool -from ._compat import PY2 -from .wsgi import ClosingIterator - -# since each thread has its own greenlet we can just use those as identifiers -# for the context. If greenlets are not available we fall back to the -# current thread ident depending on where it is. -try: - from greenlet import getcurrent as get_ident -except ImportError: - try: - from thread import get_ident - except ImportError: - from _thread import get_ident - - -def release_local(local): - """Releases the contents of the local for the current context. - This makes it possible to use locals without a manager. - - Example:: - - >>> loc = Local() - >>> loc.foo = 42 - >>> release_local(loc) - >>> hasattr(loc, 'foo') - False - - With this function one can release :class:`Local` objects as well - as :class:`LocalStack` objects. However it is not possible to - release data held by proxies that way, one always has to retain - a reference to the underlying local object in order to be able - to release it. - - .. versionadded:: 0.6.1 - """ - local.__release_local__() - - -class Local(object): - __slots__ = ("__storage__", "__ident_func__") - - def __init__(self): - object.__setattr__(self, "__storage__", {}) - object.__setattr__(self, "__ident_func__", get_ident) - - def __iter__(self): - return iter(self.__storage__.items()) - - def __call__(self, proxy): - """Create a proxy for a name.""" - return LocalProxy(self, proxy) - - def __release_local__(self): - self.__storage__.pop(self.__ident_func__(), None) - - def __getattr__(self, name): - try: - return self.__storage__[self.__ident_func__()][name] - except KeyError: - raise AttributeError(name) - - def __setattr__(self, name, value): - ident = self.__ident_func__() - storage = self.__storage__ - try: - storage[ident][name] = value - except KeyError: - storage[ident] = {name: value} - - def __delattr__(self, name): - try: - del self.__storage__[self.__ident_func__()][name] - except KeyError: - raise AttributeError(name) - - -class LocalStack(object): - """This class works similar to a :class:`Local` but keeps a stack - of objects instead. This is best explained with an example:: - - >>> ls = LocalStack() - >>> ls.push(42) - >>> ls.top - 42 - >>> ls.push(23) - >>> ls.top - 23 - >>> ls.pop() - 23 - >>> ls.top - 42 - - They can be force released by using a :class:`LocalManager` or with - the :func:`release_local` function but the correct way is to pop the - item from the stack after using. When the stack is empty it will - no longer be bound to the current context (and as such released). - - By calling the stack without arguments it returns a proxy that resolves to - the topmost item on the stack. - - .. versionadded:: 0.6.1 - """ - - def __init__(self): - self._local = Local() - - def __release_local__(self): - self._local.__release_local__() - - @property - def __ident_func__(self): - return self._local.__ident_func__ - - @__ident_func__.setter - def __ident_func__(self, value): - object.__setattr__(self._local, "__ident_func__", value) - - def __call__(self): - def _lookup(): - rv = self.top - if rv is None: - raise RuntimeError("object unbound") - return rv - - return LocalProxy(_lookup) - - def push(self, obj): - """Pushes a new item to the stack""" - rv = getattr(self._local, "stack", None) - if rv is None: - self._local.stack = rv = [] - rv.append(obj) - return rv - - def pop(self): - """Removes the topmost item from the stack, will return the - old value or `None` if the stack was already empty. - """ - stack = getattr(self._local, "stack", None) - if stack is None: - return None - elif len(stack) == 1: - release_local(self._local) - return stack[-1] - else: - return stack.pop() - - @property - def top(self): - """The topmost item on the stack. If the stack is empty, - `None` is returned. - """ - try: - return self._local.stack[-1] - except (AttributeError, IndexError): - return None - - -class LocalManager(object): - """Local objects cannot manage themselves. For that you need a local - manager. You can pass a local manager multiple locals or add them later - by appending them to `manager.locals`. Every time the manager cleans up, - it will clean up all the data left in the locals for this context. - - The `ident_func` parameter can be added to override the default ident - function for the wrapped locals. - - .. versionchanged:: 0.6.1 - Instead of a manager the :func:`release_local` function can be used - as well. - - .. versionchanged:: 0.7 - `ident_func` was added. - """ - - def __init__(self, locals=None, ident_func=None): - if locals is None: - self.locals = [] - elif isinstance(locals, Local): - self.locals = [locals] - else: - self.locals = list(locals) - if ident_func is not None: - self.ident_func = ident_func - for local in self.locals: - object.__setattr__(local, "__ident_func__", ident_func) - else: - self.ident_func = get_ident - - def get_ident(self): - """Return the context identifier the local objects use internally for - this context. You cannot override this method to change the behavior - but use it to link other context local objects (such as SQLAlchemy's - scoped sessions) to the Werkzeug locals. - - .. versionchanged:: 0.7 - You can pass a different ident function to the local manager that - will then be propagated to all the locals passed to the - constructor. - """ - return self.ident_func() - - def cleanup(self): - """Manually clean up the data in the locals for this context. Call - this at the end of the request or use `make_middleware()`. - """ - for local in self.locals: - release_local(local) - - def make_middleware(self, app): - """Wrap a WSGI application so that cleaning up happens after - request end. - """ - - def application(environ, start_response): - return ClosingIterator(app(environ, start_response), self.cleanup) - - return application - - def middleware(self, func): - """Like `make_middleware` but for decorating functions. - - Example usage:: - - @manager.middleware - def application(environ, start_response): - ... - - The difference to `make_middleware` is that the function passed - will have all the arguments copied from the inner application - (name, docstring, module). - """ - return update_wrapper(self.make_middleware(func), func) - - def __repr__(self): - return "<%s storages: %d>" % (self.__class__.__name__, len(self.locals)) - - -@implements_bool -class LocalProxy(object): - """Acts as a proxy for a werkzeug local. Forwards all operations to - a proxied object. The only operations not supported for forwarding - are right handed operands and any kind of assignment. - - Example usage:: - - from werkzeug.local import Local - l = Local() - - # these are proxies - request = l('request') - user = l('user') - - - from werkzeug.local import LocalStack - _response_local = LocalStack() - - # this is a proxy - response = _response_local() - - Whenever something is bound to l.user / l.request the proxy objects - will forward all operations. If no object is bound a :exc:`RuntimeError` - will be raised. - - To create proxies to :class:`Local` or :class:`LocalStack` objects, - call the object as shown above. If you want to have a proxy to an - object looked up by a function, you can (as of Werkzeug 0.6.1) pass - a function to the :class:`LocalProxy` constructor:: - - session = LocalProxy(lambda: get_current_request().session) - - .. versionchanged:: 0.6.1 - The class can be instantiated with a callable as well now. - """ - - __slots__ = ("__local", "__dict__", "__name__", "__wrapped__") - - def __init__(self, local, name=None): - object.__setattr__(self, "_LocalProxy__local", local) - object.__setattr__(self, "__name__", name) - if callable(local) and not hasattr(local, "__release_local__"): - # "local" is a callable that is not an instance of Local or - # LocalManager: mark it as a wrapped function. - object.__setattr__(self, "__wrapped__", local) - - def _get_current_object(self): - """Return the current object. This is useful if you want the real - object behind the proxy at a time for performance reasons or because - you want to pass the object into a different context. - """ - if not hasattr(self.__local, "__release_local__"): - return self.__local() - try: - return getattr(self.__local, self.__name__) - except AttributeError: - raise RuntimeError("no object bound to %s" % self.__name__) - - @property - def __dict__(self): - try: - return self._get_current_object().__dict__ - except RuntimeError: - raise AttributeError("__dict__") - - def __repr__(self): - try: - obj = self._get_current_object() - except RuntimeError: - return "<%s unbound>" % self.__class__.__name__ - return repr(obj) - - def __bool__(self): - try: - return bool(self._get_current_object()) - except RuntimeError: - return False - - def __unicode__(self): - try: - return unicode(self._get_current_object()) # noqa - except RuntimeError: - return repr(self) - - def __dir__(self): - try: - return dir(self._get_current_object()) - except RuntimeError: - return [] - - def __getattr__(self, name): - if name == "__members__": - return dir(self._get_current_object()) - return getattr(self._get_current_object(), name) - - def __setitem__(self, key, value): - self._get_current_object()[key] = value - - def __delitem__(self, key): - del self._get_current_object()[key] - - if PY2: - __getslice__ = lambda x, i, j: x._get_current_object()[i:j] - - def __setslice__(self, i, j, seq): - self._get_current_object()[i:j] = seq - - def __delslice__(self, i, j): - del self._get_current_object()[i:j] - - __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v) - __delattr__ = lambda x, n: delattr(x._get_current_object(), n) - __str__ = lambda x: str(x._get_current_object()) - __lt__ = lambda x, o: x._get_current_object() < o - __le__ = lambda x, o: x._get_current_object() <= o - __eq__ = lambda x, o: x._get_current_object() == o - __ne__ = lambda x, o: x._get_current_object() != o - __gt__ = lambda x, o: x._get_current_object() > o - __ge__ = lambda x, o: x._get_current_object() >= o - __cmp__ = lambda x, o: cmp(x._get_current_object(), o) # noqa - __hash__ = lambda x: hash(x._get_current_object()) - __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw) - __len__ = lambda x: len(x._get_current_object()) - __getitem__ = lambda x, i: x._get_current_object()[i] - __iter__ = lambda x: iter(x._get_current_object()) - __contains__ = lambda x, i: i in x._get_current_object() - __add__ = lambda x, o: x._get_current_object() + o - __sub__ = lambda x, o: x._get_current_object() - o - __mul__ = lambda x, o: x._get_current_object() * o - __floordiv__ = lambda x, o: x._get_current_object() // o - __mod__ = lambda x, o: x._get_current_object() % o - __divmod__ = lambda x, o: x._get_current_object().__divmod__(o) - __pow__ = lambda x, o: x._get_current_object() ** o - __lshift__ = lambda x, o: x._get_current_object() << o - __rshift__ = lambda x, o: x._get_current_object() >> o - __and__ = lambda x, o: x._get_current_object() & o - __xor__ = lambda x, o: x._get_current_object() ^ o - __or__ = lambda x, o: x._get_current_object() | o - __div__ = lambda x, o: x._get_current_object().__div__(o) - __truediv__ = lambda x, o: x._get_current_object().__truediv__(o) - __neg__ = lambda x: -(x._get_current_object()) - __pos__ = lambda x: +(x._get_current_object()) - __abs__ = lambda x: abs(x._get_current_object()) - __invert__ = lambda x: ~(x._get_current_object()) - __complex__ = lambda x: complex(x._get_current_object()) - __int__ = lambda x: int(x._get_current_object()) - __long__ = lambda x: long(x._get_current_object()) # noqa - __float__ = lambda x: float(x._get_current_object()) - __oct__ = lambda x: oct(x._get_current_object()) - __hex__ = lambda x: hex(x._get_current_object()) - __index__ = lambda x: x._get_current_object().__index__() - __coerce__ = lambda x, o: x._get_current_object().__coerce__(x, o) - __enter__ = lambda x: x._get_current_object().__enter__() - __exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw) - __radd__ = lambda x, o: o + x._get_current_object() - __rsub__ = lambda x, o: o - x._get_current_object() - __rmul__ = lambda x, o: o * x._get_current_object() - __rdiv__ = lambda x, o: o / x._get_current_object() - if PY2: - __rtruediv__ = lambda x, o: x._get_current_object().__rtruediv__(o) - else: - __rtruediv__ = __rdiv__ - __rfloordiv__ = lambda x, o: o // x._get_current_object() - __rmod__ = lambda x, o: o % x._get_current_object() - __rdivmod__ = lambda x, o: x._get_current_object().__rdivmod__(o) - __copy__ = lambda x: copy.copy(x._get_current_object()) - __deepcopy__ = lambda x, memo: copy.deepcopy(x._get_current_object(), memo) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__init__.py deleted file mode 100644 index 5e049f5..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Middleware -========== - -A WSGI middleware is a WSGI application that wraps another application -in order to observe or change its behavior. Werkzeug provides some -middleware for common use cases. - -.. toctree:: - :maxdepth: 1 - - proxy_fix - shared_data - dispatcher - http_proxy - lint - profiler - -The :doc:`interactive debugger ` is also a middleware that can -be applied manually, although it is typically used automatically with -the :doc:`development server `. - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index dd8ab958151166078c4061aacaec84cb9da35d61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcmYjP&59H;5boKFOJE4Z%uF{z#(-^54o zmG z>Jc9lAFS36H!7icb#FqvhU=?$@1eiXg3X}zpo-DiR*?-J$S8tMQjxPhkii58X<Z9|&DHKv>IICKzGSX+%5a_CVUjIbI@L*MhgLq=#- z#yk^ZHskg!CB&u?z}EC?t1*&k;HfAGx7_aJ%5F=P4b#<9D^exaHb+G*4_`t<6lJL> zp|hTf!_dk)J|sRHghq$9S#S=MYRNJ&jmx3ynCy97-1(x2=5k==4rmn3TIIzO_hO-j zUim>ew|fH0kqJX*Se>z)c9FH_%t%>-8YuKE{T|v_GJ-|F8%E_&V|NbaMMZN@gnM&noeM z*>8U?YU*PhZJZ81s`du;bYl?R^qVv;;8}tPfAY25g0NY9*Kmj2s;y7*MAXbgYMNpyWfF4p7lX;mO z*;YDUC9D2HcgeDU(eKcjNMkI;AK3PI=u1L zCk*$-%CJ-kk;r4NC5yG>r8JB)qq2iUvWJ5^+l-%6T8??iM5EcTG7r;9QmO)n^Afh+ z5P^Ywl9f_0D>)iTEwhsS^58y$dt)dcBVxGD zbUq=IA!A7~pscA@A!m?2UR#v;bP^-w9g|5lhD}X?#&OlMH zNhaWWEwn}(T%-sOh=%hmT3Mw{B+PD|`9opYu<8twr}!kNlBC8uJWGe^^}>+hfnIjw z9PxJM)cVQ>6*YLQu|KQ;30~ZV}Du=nx!~o=j<_%wHjXjjCb$ z+DS1rjF(Hd2pF;Fl0Zwp1797kvE3sPpT1X&}r=~;= z$7f#EiWbBWO3S!Rrfh%udRQRF#s=e)GLI8(fXiFK2*X~S7gJ67>alOGUHhKx0#sR= zu!r^`Gb4NK*5LN~x9eL8pBNd&=sokt$LuElW)&~#3|(|3Pq;&0w1qE%XYMc%OQQA6 z87>JAy=i%NdC`j&l;HPV$Jxr$eU(WzZz5no)4_n-xvF`+6>V6aJg5s2=g3C zJxk_B*#bDqudOKsvKXtS=}@*NkVB$nkMK!}13g0cjlM=E8iO=fBMZh^Nz6$s&|R{t zB}=Il1NX)hc~FONX2@=s9^2uCsr@Uo9H|o&-K$iri?A^bs@7`yG2ucFjUN76_?ydk zRc_@(PURIV%E1hH0Ts93@n$~4o3(1w9e)-WnT#~aYEtsIqn9weywxq!qFbn9eUcT_ zW5qgpuT0htqw#kNE8SzMA3u?kgYM!o={6ps7Z%gmaulgdl~J?~jfO5Y$8EV!zPR1o zC3?Y(jppn;BwUIP$=Hzo#H4bc+iUQJcj^o8G&t!Czw#fqbieW|=aGxqH5x1bGv{<^ z*QxyHxF|*N!ut&pr!BEmwW?s`ee9eDhaWyfS{^~8mGz->$?9(j5A$}_uKZ76QM9f* zRe;gOh!d6fl<3{=4=?O)?%j>H`#=3Wb6&dL|3GZ#$x`=3(U23GuSC(|gePY^?I;p?97VbfbNT~%5wFg@$Tv+{ u`x1XcU(3sIDzIz)j;}w$(yW#5KSJlTi|2%`t~$EwwFf^iQbP#}{Qm)UYtQij diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-37.pyc deleted file mode 100644 index dff1ab95ebdcda8fbec9cbde1eb424f495029470..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6312 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 CBMNQ+ diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-37.pyc deleted file mode 100644 index 4f87af84a9ffd35fb50df70a1a4ce4e92d287046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4574 zcmb_g&vVRdc=Lt9n_}U4t+U8$ zTSm(XZkdMR-pjH$3Ii3T3EPxuFN%e9?_6@Z?sh-Q*&yY^Sg=f{2N4%J3)mpyJQjz6 z6ioF4MMH#=GZBP+CdHGX$Q3(`R3GEQZ3Cg*4Xd@f6`;p7dKe_EFXD^=J5f<@#CB4p zVv&e&KW9O~ZIBgAB2Fy!F{bHe)*r5qr#&4Y zm*J{{rWL8#zh0(sbD-EOX=2nO9Q z166jT1Cgw-cIozRmXljN?VPU0Ka`PDB4H|Jkg8P(SAd?UX=t3#w->4HkS%z-w040?lp#QKtcAVWFkvHMX@ znwM&JyBpvlh@*9zprlgyJEJzc$J8)`D0~;D@od|~_Rh#-TSDl`i-V-x9D|+o zKvcBAenNZD>Q0=7``A#j5wb2R6Okg&lj(pR3b}tIhP&Q$gY+ufC5r|b1@O&key$%l z$L?Gra1#Tqaw({BAY_i%h5aDe6&$Lpd%ybd9Ais!kBZ==)C!bj7Ez_13B!eoN;^hb z@y=m*Mb-;tuVnI_33IjZRH1Rg$D>Rf#dNs>Xj`S$Lb8f0r(l&ubvEC}}n zUp?##5wAY+`yWK;S(^}fZA#>|3S4^G2-?Z&FWY=J+gR{ z8DWj2anX61bfV|{w>X&Y8sAv_`b+Dj-NWgKTQBCmF^7&Wxv7@f+&0{^F zkDW8?*nu7kxPu<(Tcj2LZpw9ab!_YBg;&<`+<0zp2~XGliW9q9=8Jmd>MOhh;A!a; zTG0CZ+8L~vj$zhyJl&{fEzgWJc1_Uj#>Tlz$(1&~*U6>JXimUc@YZ@>gJQ;B#ZI$m zfK4Ldtr}4(P{X`v_C>%^Sqeuy4H4X4iey>PD@z1t|PL7ac&eFs!XD0G1-QzKXKfOx{t69aKD zPOMXyOmR?1RBk@Ef+c%h%QcUF`Mqo|XaA2T7K>j! z`0|erwzmB*9&CU9=zeEz^WOI7{=x{C?zZfrQ6BXQn<^ai zEYD-I0fCk&uj1!ubM*(l@UCN1g*kFby*7LHGkIJXM_>NH%dEOoPJbkcL)xHD6TTwK z6!u;kC6a1S;ZO%1uH*teHp=sKQQH-&sM84nl~@XF?4c;EG?zbzRLAARK~^4+QE1!A0{uYOU`m$t7~jp@L3_CEqVx-!EVIaX;_-PliEUjWm6qry;s)`6#Et!PB9V z__M>1A5x>UVcL-Pl3sn^#W$yXaaQcQZCd&>Kc~l9SLH2?(5k&5&STI((ym)H)7&FE zOL}LPZEA?mokn@aEraDu{!`HWD6TxzN2~`@rc$mGN+aFb!@Hke>N5Qb=XPoAM?{?b U1{xdwbKqGAzm~ZK4=&gK4;^kWApigX diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-37.pyc deleted file mode 100644 index 41fbf1c62c48ee676d4698998bc182d385c3aca2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5757 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"`` (default): - The host header is automatically rewritten to the URL of the - target. - ``None``: - The host header is unmodified from the client request. - Any other value: - The host header is overwritten with the value. - ``headers``: - A dictionary of headers to be sent with the request to the - target. The default is ``{}``. - ``ssl_context``: - A :class:`ssl.SSLContext` defining how to verify requests if the - target is HTTPS. The default is ``None``. - - In the example above, everything under ``"/static/"`` is proxied to - the server on port 5001. The host header is rewritten to the target, - and the ``"/static/"`` prefix is removed from the URLs. - - :param app: The WSGI application to wrap. - :param targets: Proxy target configurations. See description above. - :param chunk_size: Size of chunks to read from input stream and - write to target. - :param timeout: Seconds before an operation to a target fails. - - .. versionadded:: 0.14 - """ - - def __init__(self, app, targets, chunk_size=2 << 13, timeout=10): - def _set_defaults(opts): - opts.setdefault("remove_prefix", False) - opts.setdefault("host", "") - opts.setdefault("headers", {}) - opts.setdefault("ssl_context", None) - return opts - - self.app = app - self.targets = dict( - ("/%s/" % k.strip("/"), _set_defaults(v)) for k, v in targets.items() - ) - self.chunk_size = chunk_size - self.timeout = timeout - - def proxy_to(self, opts, path, prefix): - target = url_parse(opts["target"]) - - def application(environ, start_response): - headers = list(EnvironHeaders(environ).items()) - headers[:] = [ - (k, v) - for k, v in headers - if not is_hop_by_hop_header(k) - and k.lower() not in ("content-length", "host") - ] - headers.append(("Connection", "close")) - - if opts["host"] == "": - headers.append(("Host", target.ascii_host)) - elif opts["host"] is None: - headers.append(("Host", environ["HTTP_HOST"])) - else: - headers.append(("Host", opts["host"])) - - headers.extend(opts["headers"].items()) - remote_path = path - - if opts["remove_prefix"]: - remote_path = "%s/%s" % ( - target.path.rstrip("/"), - remote_path[len(prefix) :].lstrip("/"), - ) - - content_length = environ.get("CONTENT_LENGTH") - chunked = False - - if content_length not in ("", None): - headers.append(("Content-Length", content_length)) - elif content_length is not None: - headers.append(("Transfer-Encoding", "chunked")) - chunked = True - - try: - if target.scheme == "http": - con = client.HTTPConnection( - target.ascii_host, target.port or 80, timeout=self.timeout - ) - elif target.scheme == "https": - con = client.HTTPSConnection( - target.ascii_host, - target.port or 443, - timeout=self.timeout, - context=opts["ssl_context"], - ) - else: - raise RuntimeError( - "Target scheme must be 'http' or 'https', got '{}'.".format( - target.scheme - ) - ) - - con.connect() - remote_url = url_quote(remote_path) - querystring = environ["QUERY_STRING"] - - if querystring: - remote_url = remote_url + "?" + querystring - - con.putrequest(environ["REQUEST_METHOD"], remote_url, skip_host=True) - - for k, v in headers: - if k.lower() == "connection": - v = "close" - - con.putheader(k, v) - - con.endheaders() - stream = get_input_stream(environ) - - while 1: - data = stream.read(self.chunk_size) - - if not data: - break - - if chunked: - con.send(b"%x\r\n%s\r\n" % (len(data), data)) - else: - con.send(data) - - resp = con.getresponse() - except socket.error: - from ..exceptions import BadGateway - - return BadGateway()(environ, start_response) - - start_response( - "%d %s" % (resp.status, resp.reason), - [ - (k.title(), v) - for k, v in resp.getheaders() - if not is_hop_by_hop_header(k) - ], - ) - - def read(): - while 1: - try: - data = resp.read(self.chunk_size) - except socket.error: - break - - if not data: - break - - yield data - - return read() - - return application - - def __call__(self, environ, start_response): - path = environ["PATH_INFO"] - app = self.app - - for prefix, opts in self.targets.items(): - if path.startswith(prefix): - app = self.proxy_to(opts, path, prefix) - break - - return app(environ, start_response) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/lint.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/lint.py deleted file mode 100644 index 98f9581..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/lint.py +++ /dev/null @@ -1,408 +0,0 @@ -""" -WSGI Protocol Linter -==================== - -This module provides a middleware that performs sanity checks on the -behavior of the WSGI server and application. It checks that the -:pep:`3333` WSGI spec is properly implemented. It also warns on some -common HTTP errors such as non-empty responses for 304 status codes. - -.. autoclass:: LintMiddleware - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" -from warnings import warn - -from .._compat import implements_iterator -from .._compat import PY2 -from .._compat import string_types -from ..datastructures import Headers -from ..http import is_entity_header -from ..wsgi import FileWrapper - -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse - - -class WSGIWarning(Warning): - """Warning class for WSGI warnings.""" - - -class HTTPWarning(Warning): - """Warning class for HTTP warnings.""" - - -def check_string(context, obj, stacklevel=3): - if type(obj) is not str: - warn( - "'%s' requires strings, got '%s'" % (context, type(obj).__name__), - WSGIWarning, - ) - - -class InputStream(object): - def __init__(self, stream): - self._stream = stream - - def read(self, *args): - if len(args) == 0: - warn( - "WSGI does not guarantee an EOF marker on the input stream, thus making" - " calls to 'wsgi.input.read()' unsafe. Conforming servers may never" - " return from this call.", - WSGIWarning, - stacklevel=2, - ) - elif len(args) != 1: - warn( - "Too many parameters passed to 'wsgi.input.read()'.", - WSGIWarning, - stacklevel=2, - ) - return self._stream.read(*args) - - def readline(self, *args): - if len(args) == 0: - warn( - "Calls to 'wsgi.input.readline()' without arguments are unsafe. Use" - " 'wsgi.input.read()' instead.", - WSGIWarning, - stacklevel=2, - ) - elif len(args) == 1: - warn( - "'wsgi.input.readline()' was called with a size hint. WSGI does not" - " support this, although it's available on all major servers.", - WSGIWarning, - stacklevel=2, - ) - else: - raise TypeError("Too many arguments passed to 'wsgi.input.readline()'.") - return self._stream.readline(*args) - - def __iter__(self): - try: - return iter(self._stream) - except TypeError: - warn("'wsgi.input' is not iterable.", WSGIWarning, stacklevel=2) - return iter(()) - - def close(self): - warn("The application closed the input stream!", WSGIWarning, stacklevel=2) - self._stream.close() - - -class ErrorStream(object): - def __init__(self, stream): - self._stream = stream - - def write(self, s): - check_string("wsgi.error.write()", s) - self._stream.write(s) - - def flush(self): - self._stream.flush() - - def writelines(self, seq): - for line in seq: - self.write(line) - - def close(self): - warn("The application closed the error stream!", WSGIWarning, stacklevel=2) - self._stream.close() - - -class GuardedWrite(object): - def __init__(self, write, chunks): - self._write = write - self._chunks = chunks - - def __call__(self, s): - check_string("write()", s) - self._write.write(s) - self._chunks.append(len(s)) - - -@implements_iterator -class GuardedIterator(object): - def __init__(self, iterator, headers_set, chunks): - self._iterator = iterator - if PY2: - self._next = iter(iterator).next - else: - self._next = iter(iterator).__next__ - self.closed = False - self.headers_set = headers_set - self.chunks = chunks - - def __iter__(self): - return self - - def __next__(self): - if self.closed: - warn("Iterated over closed 'app_iter'.", WSGIWarning, stacklevel=2) - - rv = self._next() - - if not self.headers_set: - warn( - "The application returned before it started the response.", - WSGIWarning, - stacklevel=2, - ) - - check_string("application iterator items", rv) - self.chunks.append(len(rv)) - return rv - - def close(self): - self.closed = True - - if hasattr(self._iterator, "close"): - self._iterator.close() - - if self.headers_set: - status_code, headers = self.headers_set - bytes_sent = sum(self.chunks) - content_length = headers.get("content-length", type=int) - - if status_code == 304: - for key, _value in headers: - key = key.lower() - if key not in ("expires", "content-location") and is_entity_header( - key - ): - warn( - "Entity header %r found in 304 response." % key, HTTPWarning - ) - if bytes_sent: - warn("304 responses must not have a body.", HTTPWarning) - elif 100 <= status_code < 200 or status_code == 204: - if content_length != 0: - warn( - "%r responses must have an empty content length." % status_code, - HTTPWarning, - ) - if bytes_sent: - warn( - "%r responses must not have a body." % status_code, HTTPWarning - ) - elif content_length is not None and content_length != bytes_sent: - warn( - "Content-Length and the number of bytes sent to the client do not" - " match.", - WSGIWarning, - ) - - def __del__(self): - if not self.closed: - try: - warn( - "Iterator was garbage collected before it was closed.", WSGIWarning - ) - except Exception: - pass - - -class LintMiddleware(object): - """Warns about common errors in the WSGI and HTTP behavior of the - server and wrapped application. Some of the issues it check are: - - - invalid status codes - - non-bytestrings sent to the WSGI server - - strings returned from the WSGI application - - non-empty conditional responses - - unquoted etags - - relative URLs in the Location header - - unsafe calls to wsgi.input - - unclosed iterators - - Error information is emitted using the :mod:`warnings` module. - - :param app: The WSGI application to wrap. - - .. code-block:: python - - from werkzeug.middleware.lint import LintMiddleware - app = LintMiddleware(app) - """ - - def __init__(self, app): - self.app = app - - def check_environ(self, environ): - if type(environ) is not dict: - warn( - "WSGI environment is not a standard Python dict.", - WSGIWarning, - stacklevel=4, - ) - for key in ( - "REQUEST_METHOD", - "SERVER_NAME", - "SERVER_PORT", - "wsgi.version", - "wsgi.input", - "wsgi.errors", - "wsgi.multithread", - "wsgi.multiprocess", - "wsgi.run_once", - ): - if key not in environ: - warn( - "Required environment key %r not found" % key, - WSGIWarning, - stacklevel=3, - ) - if environ["wsgi.version"] != (1, 0): - warn("Environ is not a WSGI 1.0 environ.", WSGIWarning, stacklevel=3) - - script_name = environ.get("SCRIPT_NAME", "") - path_info = environ.get("PATH_INFO", "") - - if script_name and script_name[0] != "/": - warn( - "'SCRIPT_NAME' does not start with a slash: %r" % script_name, - WSGIWarning, - stacklevel=3, - ) - - if path_info and path_info[0] != "/": - warn( - "'PATH_INFO' does not start with a slash: %r" % path_info, - WSGIWarning, - stacklevel=3, - ) - - def check_start_response(self, status, headers, exc_info): - check_string("status", status) - status_code = status.split(None, 1)[0] - - if len(status_code) != 3 or not status_code.isdigit(): - warn(WSGIWarning("Status code must be three digits"), stacklevel=3) - - if len(status) < 4 or status[3] != " ": - warn( - WSGIWarning( - "Invalid value for status %r. Valid " - "status strings are three digits, a space " - "and a status explanation" - ), - stacklevel=3, - ) - - status_code = int(status_code) - - if status_code < 100: - warn(WSGIWarning("status code < 100 detected"), stacklevel=3) - - if type(headers) is not list: - warn(WSGIWarning("header list is not a list"), stacklevel=3) - - for item in headers: - if type(item) is not tuple or len(item) != 2: - warn(WSGIWarning("Headers must tuple 2-item tuples"), stacklevel=3) - name, value = item - if type(name) is not str or type(value) is not str: - warn(WSGIWarning("header items must be strings"), stacklevel=3) - if name.lower() == "status": - warn( - WSGIWarning( - "The status header is not supported due to " - "conflicts with the CGI spec." - ), - stacklevel=3, - ) - - if exc_info is not None and not isinstance(exc_info, tuple): - warn(WSGIWarning("invalid value for exc_info"), stacklevel=3) - - headers = Headers(headers) - self.check_headers(headers) - - return status_code, headers - - def check_headers(self, headers): - etag = headers.get("etag") - - if etag is not None: - if etag.startswith(("W/", "w/")): - if etag.startswith("w/"): - warn( - HTTPWarning("weak etag indicator should be upcase."), - stacklevel=4, - ) - - etag = etag[2:] - - if not (etag[:1] == etag[-1:] == '"'): - warn(HTTPWarning("unquoted etag emitted."), stacklevel=4) - - location = headers.get("location") - - if location is not None: - if not urlparse(location).netloc: - warn( - HTTPWarning("absolute URLs required for location header"), - stacklevel=4, - ) - - def check_iterator(self, app_iter): - if isinstance(app_iter, string_types): - warn( - "The application returned astring. The response will send one character" - " at a time to the client, which will kill performance. Return a list" - " or iterable instead.", - WSGIWarning, - stacklevel=3, - ) - - def __call__(self, *args, **kwargs): - if len(args) != 2: - warn("A WSGI app takes two arguments.", WSGIWarning, stacklevel=2) - - if kwargs: - warn( - "A WSGI app does not take keyword arguments.", WSGIWarning, stacklevel=2 - ) - - environ, start_response = args - - self.check_environ(environ) - environ["wsgi.input"] = InputStream(environ["wsgi.input"]) - environ["wsgi.errors"] = ErrorStream(environ["wsgi.errors"]) - - # Hook our own file wrapper in so that applications will always - # iterate to the end and we can check the content length. - environ["wsgi.file_wrapper"] = FileWrapper - - headers_set = [] - chunks = [] - - def checking_start_response(*args, **kwargs): - if len(args) not in (2, 3): - warn( - "Invalid number of arguments: %s, expected 2 or 3." % len(args), - WSGIWarning, - stacklevel=2, - ) - - if kwargs: - warn("'start_response' does not take keyword arguments.", WSGIWarning) - - status, headers = args[:2] - - if len(args) == 3: - exc_info = args[2] - else: - exc_info = None - - headers_set[:] = self.check_start_response(status, headers, exc_info) - return GuardedWrite(start_response(status, headers, exc_info), chunks) - - app_iter = self.app(environ, checking_start_response) - self.check_iterator(app_iter) - return GuardedIterator(app_iter, headers_set, chunks) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/profiler.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/profiler.py deleted file mode 100644 index 32a14d9..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/profiler.py +++ /dev/null @@ -1,132 +0,0 @@ -""" -Application Profiler -==================== - -This module provides a middleware that profiles each request with the -:mod:`cProfile` module. This can help identify bottlenecks in your code -that may be slowing down your application. - -.. autoclass:: ProfilerMiddleware - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" -from __future__ import print_function - -import os.path -import sys -import time -from pstats import Stats - -try: - from cProfile import Profile -except ImportError: - from profile import Profile - - -class ProfilerMiddleware(object): - """Wrap a WSGI application and profile the execution of each - request. Responses are buffered so that timings are more exact. - - If ``stream`` is given, :class:`pstats.Stats` are written to it - after each request. If ``profile_dir`` is given, :mod:`cProfile` - data files are saved to that directory, one file per request. - - The filename can be customized by passing ``filename_format``. If - it is a string, it will be formatted using :meth:`str.format` with - the following fields available: - - - ``{method}`` - The request method; GET, POST, etc. - - ``{path}`` - The request path or 'root' should one not exist. - - ``{elapsed}`` - The elapsed time of the request. - - ``{time}`` - The time of the request. - - If it is a callable, it will be called with the WSGI ``environ`` - dict and should return a filename. - - :param app: The WSGI application to wrap. - :param stream: Write stats to this stream. Disable with ``None``. - :param sort_by: A tuple of columns to sort stats by. See - :meth:`pstats.Stats.sort_stats`. - :param restrictions: A tuple of restrictions to filter stats by. See - :meth:`pstats.Stats.print_stats`. - :param profile_dir: Save profile data files to this directory. - :param filename_format: Format string for profile data file names, - or a callable returning a name. See explanation above. - - .. code-block:: python - - from werkzeug.middleware.profiler import ProfilerMiddleware - app = ProfilerMiddleware(app) - - .. versionchanged:: 0.15 - Stats are written even if ``profile_dir`` is given, and can be - disable by passing ``stream=None``. - - .. versionadded:: 0.15 - Added ``filename_format``. - - .. versionadded:: 0.9 - Added ``restrictions`` and ``profile_dir``. - """ - - def __init__( - self, - app, - stream=sys.stdout, - sort_by=("time", "calls"), - restrictions=(), - profile_dir=None, - filename_format="{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof", - ): - self._app = app - self._stream = stream - self._sort_by = sort_by - self._restrictions = restrictions - self._profile_dir = profile_dir - self._filename_format = filename_format - - def __call__(self, environ, start_response): - response_body = [] - - def catching_start_response(status, headers, exc_info=None): - start_response(status, headers, exc_info) - return response_body.append - - def runapp(): - app_iter = self._app(environ, catching_start_response) - response_body.extend(app_iter) - - if hasattr(app_iter, "close"): - app_iter.close() - - profile = Profile() - start = time.time() - profile.runcall(runapp) - body = b"".join(response_body) - elapsed = time.time() - start - - if self._profile_dir is not None: - if callable(self._filename_format): - filename = self._filename_format(environ) - else: - filename = self._filename_format.format( - method=environ["REQUEST_METHOD"], - path=( - environ.get("PATH_INFO").strip("/").replace("/", ".") or "root" - ), - elapsed=elapsed * 1000.0, - time=time.time(), - ) - filename = os.path.join(self._profile_dir, filename) - profile.dump_stats(filename) - - if self._stream is not None: - stats = Stats(profile, stream=self._stream) - stats.sort_stats(*self._sort_by) - print("-" * 80, file=self._stream) - print("PATH: {!r}".format(environ.get("PATH_INFO", "")), file=self._stream) - stats.print_stats(*self._restrictions) - print("-" * 80 + "\n", file=self._stream) - - return [body] diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/proxy_fix.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/proxy_fix.py deleted file mode 100644 index f393f61..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/proxy_fix.py +++ /dev/null @@ -1,169 +0,0 @@ -""" -X-Forwarded-For Proxy Fix -========================= - -This module provides a middleware that adjusts the WSGI environ based on -``X-Forwarded-`` headers that proxies in front of an application may -set. - -When an application is running behind a proxy server, WSGI may see the -request as coming from that server rather than the real client. Proxies -set various headers to track where the request actually came from. - -This middleware should only be applied if the application is actually -behind such a proxy, and should be configured with the number of proxies -that are chained in front of it. Not all proxies set all the headers. -Since incoming headers can be faked, you must set how many proxies are -setting each header so the middleware knows what to trust. - -.. autoclass:: ProxyFix - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" -from werkzeug.http import parse_list_header - - -class ProxyFix(object): - """Adjust the WSGI environ based on ``X-Forwarded-`` that proxies in - front of the application may set. - - - ``X-Forwarded-For`` sets ``REMOTE_ADDR``. - - ``X-Forwarded-Proto`` sets ``wsgi.url_scheme``. - - ``X-Forwarded-Host`` sets ``HTTP_HOST``, ``SERVER_NAME``, and - ``SERVER_PORT``. - - ``X-Forwarded-Port`` sets ``HTTP_HOST`` and ``SERVER_PORT``. - - ``X-Forwarded-Prefix`` sets ``SCRIPT_NAME``. - - You must tell the middleware how many proxies set each header so it - knows what values to trust. It is a security issue to trust values - that came from the client rather than a proxy. - - The original values of the headers are stored in the WSGI - environ as ``werkzeug.proxy_fix.orig``, a dict. - - :param app: The WSGI application to wrap. - :param x_for: Number of values to trust for ``X-Forwarded-For``. - :param x_proto: Number of values to trust for ``X-Forwarded-Proto``. - :param x_host: Number of values to trust for ``X-Forwarded-Host``. - :param x_port: Number of values to trust for ``X-Forwarded-Port``. - :param x_prefix: Number of values to trust for - ``X-Forwarded-Prefix``. - - .. code-block:: python - - from werkzeug.middleware.proxy_fix import ProxyFix - # App is behind one proxy that sets the -For and -Host headers. - app = ProxyFix(app, x_for=1, x_host=1) - - .. versionchanged:: 1.0 - Deprecated code has been removed: - - * The ``num_proxies`` argument and attribute. - * The ``get_remote_addr`` method. - * The environ keys ``orig_remote_addr``, - ``orig_wsgi_url_scheme``, and ``orig_http_host``. - - .. versionchanged:: 0.15 - All headers support multiple values. The ``num_proxies`` - argument is deprecated. Each header is configured with a - separate number of trusted proxies. - - .. versionchanged:: 0.15 - Original WSGI environ values are stored in the - ``werkzeug.proxy_fix.orig`` dict. ``orig_remote_addr``, - ``orig_wsgi_url_scheme``, and ``orig_http_host`` are deprecated - and will be removed in 1.0. - - .. versionchanged:: 0.15 - Support ``X-Forwarded-Port`` and ``X-Forwarded-Prefix``. - - .. versionchanged:: 0.15 - ``X-Forwarded-Host`` and ``X-Forwarded-Port`` modify - ``SERVER_NAME`` and ``SERVER_PORT``. - """ - - def __init__(self, app, x_for=1, x_proto=1, x_host=0, x_port=0, x_prefix=0): - self.app = app - self.x_for = x_for - self.x_proto = x_proto - self.x_host = x_host - self.x_port = x_port - self.x_prefix = x_prefix - - def _get_real_value(self, trusted, value): - """Get the real value from a list header based on the configured - number of trusted proxies. - - :param trusted: Number of values to trust in the header. - :param value: Comma separated list header value to parse. - :return: The real value, or ``None`` if there are fewer values - than the number of trusted proxies. - - .. versionchanged:: 1.0 - Renamed from ``_get_trusted_comma``. - - .. versionadded:: 0.15 - """ - if not (trusted and value): - return - values = parse_list_header(value) - if len(values) >= trusted: - return values[-trusted] - - def __call__(self, environ, start_response): - """Modify the WSGI environ based on the various ``Forwarded`` - headers before calling the wrapped application. Store the - original environ values in ``werkzeug.proxy_fix.orig_{key}``. - """ - environ_get = environ.get - orig_remote_addr = environ_get("REMOTE_ADDR") - orig_wsgi_url_scheme = environ_get("wsgi.url_scheme") - orig_http_host = environ_get("HTTP_HOST") - environ.update( - { - "werkzeug.proxy_fix.orig": { - "REMOTE_ADDR": orig_remote_addr, - "wsgi.url_scheme": orig_wsgi_url_scheme, - "HTTP_HOST": orig_http_host, - "SERVER_NAME": environ_get("SERVER_NAME"), - "SERVER_PORT": environ_get("SERVER_PORT"), - "SCRIPT_NAME": environ_get("SCRIPT_NAME"), - } - } - ) - - x_for = self._get_real_value(self.x_for, environ_get("HTTP_X_FORWARDED_FOR")) - if x_for: - environ["REMOTE_ADDR"] = x_for - - x_proto = self._get_real_value( - self.x_proto, environ_get("HTTP_X_FORWARDED_PROTO") - ) - if x_proto: - environ["wsgi.url_scheme"] = x_proto - - x_host = self._get_real_value(self.x_host, environ_get("HTTP_X_FORWARDED_HOST")) - if x_host: - environ["HTTP_HOST"] = x_host - parts = x_host.split(":", 1) - environ["SERVER_NAME"] = parts[0] - if len(parts) == 2: - environ["SERVER_PORT"] = parts[1] - - x_port = self._get_real_value(self.x_port, environ_get("HTTP_X_FORWARDED_PORT")) - if x_port: - host = environ.get("HTTP_HOST") - if host: - parts = host.split(":", 1) - host = parts[0] if len(parts) == 2 else host - environ["HTTP_HOST"] = "%s:%s" % (host, x_port) - environ["SERVER_PORT"] = x_port - - x_prefix = self._get_real_value( - self.x_prefix, environ_get("HTTP_X_FORWARDED_PREFIX") - ) - if x_prefix: - environ["SCRIPT_NAME"] = x_prefix - - return self.app(environ, start_response) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/shared_data.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/shared_data.py deleted file mode 100644 index b6e3764..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/middleware/shared_data.py +++ /dev/null @@ -1,293 +0,0 @@ -""" -Serve Shared Static Files -========================= - -.. autoclass:: SharedDataMiddleware - :members: is_allowed - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" -import mimetypes -import os -import pkgutil -import posixpath -from datetime import datetime -from io import BytesIO -from time import mktime -from time import time -from zlib import adler32 - -from .._compat import PY2 -from .._compat import string_types -from ..filesystem import get_filesystem_encoding -from ..http import http_date -from ..http import is_resource_modified -from ..security import safe_join -from ..utils import get_content_type -from ..wsgi import get_path_info -from ..wsgi import wrap_file - - -class SharedDataMiddleware(object): - - """A WSGI middleware that provides static content for development - environments or simple server setups. Usage is quite simple:: - - import os - from werkzeug.middleware.shared_data import SharedDataMiddleware - - app = SharedDataMiddleware(app, { - '/static': os.path.join(os.path.dirname(__file__), 'static') - }) - - The contents of the folder ``./shared`` will now be available on - ``http://example.com/shared/``. This is pretty useful during development - because a standalone media server is not required. One can also mount - files on the root folder and still continue to use the application because - the shared data middleware forwards all unhandled requests to the - application, even if the requests are below one of the shared folders. - - If `pkg_resources` is available you can also tell the middleware to serve - files from package data:: - - app = SharedDataMiddleware(app, { - '/static': ('myapplication', 'static') - }) - - This will then serve the ``static`` folder in the `myapplication` - Python package. - - The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch` - rules for files that are not accessible from the web. If `cache` is set to - `False` no caching headers are sent. - - Currently the middleware does not support non ASCII filenames. If the - encoding on the file system happens to be the encoding of the URI it may - work but this could also be by accident. We strongly suggest using ASCII - only file names for static files. - - The middleware will guess the mimetype using the Python `mimetype` - module. If it's unable to figure out the charset it will fall back - to `fallback_mimetype`. - - :param app: the application to wrap. If you don't want to wrap an - application you can pass it :exc:`NotFound`. - :param exports: a list or dict of exported files and folders. - :param disallow: a list of :func:`~fnmatch.fnmatch` rules. - :param cache: enable or disable caching headers. - :param cache_timeout: the cache timeout in seconds for the headers. - :param fallback_mimetype: The fallback mimetype for unknown files. - - .. versionchanged:: 1.0 - The default ``fallback_mimetype`` is - ``application/octet-stream``. If a filename looks like a text - mimetype, the ``utf-8`` charset is added to it. - - .. versionadded:: 0.6 - Added ``fallback_mimetype``. - - .. versionchanged:: 0.5 - Added ``cache_timeout``. - """ - - def __init__( - self, - app, - exports, - disallow=None, - cache=True, - cache_timeout=60 * 60 * 12, - fallback_mimetype="application/octet-stream", - ): - self.app = app - self.exports = [] - self.cache = cache - self.cache_timeout = cache_timeout - - if hasattr(exports, "items"): - exports = exports.items() - - for key, value in exports: - if isinstance(value, tuple): - loader = self.get_package_loader(*value) - elif isinstance(value, string_types): - if os.path.isfile(value): - loader = self.get_file_loader(value) - else: - loader = self.get_directory_loader(value) - else: - raise TypeError("unknown def %r" % value) - - self.exports.append((key, loader)) - - if disallow is not None: - from fnmatch import fnmatch - - self.is_allowed = lambda x: not fnmatch(x, disallow) - - self.fallback_mimetype = fallback_mimetype - - def is_allowed(self, filename): - """Subclasses can override this method to disallow the access to - certain files. However by providing `disallow` in the constructor - this method is overwritten. - """ - return True - - def _opener(self, filename): - return lambda: ( - open(filename, "rb"), - datetime.utcfromtimestamp(os.path.getmtime(filename)), - int(os.path.getsize(filename)), - ) - - def get_file_loader(self, filename): - return lambda x: (os.path.basename(filename), self._opener(filename)) - - def get_package_loader(self, package, package_path): - loadtime = datetime.utcnow() - provider = pkgutil.get_loader(package) - - if hasattr(provider, "get_resource_reader"): - # Python 3 - reader = provider.get_resource_reader(package) - - def loader(path): - if path is None: - return None, None - - path = safe_join(package_path, path) - basename = posixpath.basename(path) - - try: - resource = reader.open_resource(path) - except IOError: - return None, None - - if isinstance(resource, BytesIO): - return ( - basename, - lambda: (resource, loadtime, len(resource.getvalue())), - ) - - return ( - basename, - lambda: ( - resource, - datetime.utcfromtimestamp(os.path.getmtime(resource.name)), - os.path.getsize(resource.name), - ), - ) - - else: - # Python 2 - package_filename = provider.get_filename(package) - is_filesystem = os.path.exists(package_filename) - root = os.path.join(os.path.dirname(package_filename), package_path) - - def loader(path): - if path is None: - return None, None - - path = safe_join(root, path) - basename = posixpath.basename(path) - - if is_filesystem: - if not os.path.isfile(path): - return None, None - - return basename, self._opener(path) - - try: - data = provider.get_data(path) - except IOError: - return None, None - - return basename, lambda: (BytesIO(data), loadtime, len(data)) - - return loader - - def get_directory_loader(self, directory): - def loader(path): - if path is not None: - path = safe_join(directory, path) - else: - path = directory - - if os.path.isfile(path): - return os.path.basename(path), self._opener(path) - - return None, None - - return loader - - def generate_etag(self, mtime, file_size, real_filename): - if not isinstance(real_filename, bytes): - real_filename = real_filename.encode(get_filesystem_encoding()) - - return "wzsdm-%d-%s-%s" % ( - mktime(mtime.timetuple()), - file_size, - adler32(real_filename) & 0xFFFFFFFF, - ) - - def __call__(self, environ, start_response): - path = get_path_info(environ) - - if PY2: - path = path.encode(get_filesystem_encoding()) - - file_loader = None - - for search_path, loader in self.exports: - if search_path == path: - real_filename, file_loader = loader(None) - - if file_loader is not None: - break - - if not search_path.endswith("/"): - search_path += "/" - - if path.startswith(search_path): - real_filename, file_loader = loader(path[len(search_path) :]) - - if file_loader is not None: - break - - if file_loader is None or not self.is_allowed(real_filename): - return self.app(environ, start_response) - - guessed_type = mimetypes.guess_type(real_filename) - mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype, "utf-8") - f, mtime, file_size = file_loader() - - headers = [("Date", http_date())] - - if self.cache: - timeout = self.cache_timeout - etag = self.generate_etag(mtime, file_size, real_filename) - headers += [ - ("Etag", '"%s"' % etag), - ("Cache-Control", "max-age=%d, public" % timeout), - ] - - if not is_resource_modified(environ, etag, last_modified=mtime): - f.close() - start_response("304 Not Modified", headers) - return [] - - headers.append(("Expires", http_date(time() + timeout))) - else: - headers.append(("Cache-Control", "public")) - - headers.extend( - ( - ("Content-Type", mime_type), - ("Content-Length", str(file_size)), - ("Last-Modified", http_date(mtime)), - ) - ) - start_response("200 OK", headers) - return wrap_file(environ, f) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/posixemulation.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/posixemulation.py deleted file mode 100644 index 696b456..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/posixemulation.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -r""" - werkzeug.posixemulation - ~~~~~~~~~~~~~~~~~~~~~~~ - - Provides a POSIX emulation for some features that are relevant to - web applications. The main purpose is to simplify support for - systems such as Windows NT that are not 100% POSIX compatible. - - Currently this only implements a :func:`rename` function that - follows POSIX semantics. Eg: if the target file already exists it - will be replaced without asking. - - This module was introduced in 0.6.1 and is not a public interface. - It might become one in later versions of Werkzeug. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import errno -import os -import random -import sys -import time - -from ._compat import to_unicode -from .filesystem import get_filesystem_encoding - -can_rename_open_file = False - -if os.name == "nt": - try: - import ctypes - - _MOVEFILE_REPLACE_EXISTING = 0x1 - _MOVEFILE_WRITE_THROUGH = 0x8 - _MoveFileEx = ctypes.windll.kernel32.MoveFileExW - - def _rename(src, dst): - src = to_unicode(src, get_filesystem_encoding()) - dst = to_unicode(dst, get_filesystem_encoding()) - if _rename_atomic(src, dst): - return True - retry = 0 - rv = False - while not rv and retry < 100: - rv = _MoveFileEx( - src, dst, _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH - ) - if not rv: - time.sleep(0.001) - retry += 1 - return rv - - # new in Vista and Windows Server 2008 - _CreateTransaction = ctypes.windll.ktmw32.CreateTransaction - _CommitTransaction = ctypes.windll.ktmw32.CommitTransaction - _MoveFileTransacted = ctypes.windll.kernel32.MoveFileTransactedW - _CloseHandle = ctypes.windll.kernel32.CloseHandle - can_rename_open_file = True - - def _rename_atomic(src, dst): - ta = _CreateTransaction(None, 0, 0, 0, 0, 1000, "Werkzeug rename") - if ta == -1: - return False - try: - retry = 0 - rv = False - while not rv and retry < 100: - rv = _MoveFileTransacted( - src, - dst, - None, - None, - _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH, - ta, - ) - if rv: - rv = _CommitTransaction(ta) - break - else: - time.sleep(0.001) - retry += 1 - return rv - finally: - _CloseHandle(ta) - - except Exception: - - def _rename(src, dst): - return False - - def _rename_atomic(src, dst): - return False - - def rename(src, dst): - # Try atomic or pseudo-atomic rename - if _rename(src, dst): - return - # Fall back to "move away and replace" - try: - os.rename(src, dst) - except OSError as e: - if e.errno != errno.EEXIST: - raise - old = "%s-%08x" % (dst, random.randint(0, sys.maxsize)) - os.rename(dst, old) - os.rename(src, dst) - try: - os.unlink(old) - except Exception: - pass - - -else: - rename = os.rename - can_rename_open_file = True diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/routing.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/routing.py deleted file mode 100644 index e090c66..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/routing.py +++ /dev/null @@ -1,2210 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.routing - ~~~~~~~~~~~~~~~~ - - When it comes to combining multiple controller or view functions (however - you want to call them) you need a dispatcher. A simple way would be - applying regular expression tests on the ``PATH_INFO`` and calling - registered callback functions that return the value then. - - This module implements a much more powerful system than simple regular - expression matching because it can also convert values in the URLs and - build URLs. - - Here a simple example that creates an URL map for an application with - two subdomains (www and kb) and some URL rules: - - >>> m = Map([ - ... # Static URLs - ... Rule('/', endpoint='static/index'), - ... Rule('/about', endpoint='static/about'), - ... Rule('/help', endpoint='static/help'), - ... # Knowledge Base - ... Subdomain('kb', [ - ... Rule('/', endpoint='kb/index'), - ... Rule('/browse/', endpoint='kb/browse'), - ... Rule('/browse//', endpoint='kb/browse'), - ... Rule('/browse//', endpoint='kb/browse') - ... ]) - ... ], default_subdomain='www') - - If the application doesn't use subdomains it's perfectly fine to not set - the default subdomain and not use the `Subdomain` rule factory. The endpoint - in the rules can be anything, for example import paths or unique - identifiers. The WSGI application can use those endpoints to get the - handler for that URL. It doesn't have to be a string at all but it's - recommended. - - Now it's possible to create a URL adapter for one of the subdomains and - build URLs: - - >>> c = m.bind('example.com') - >>> c.build("kb/browse", dict(id=42)) - 'http://kb.example.com/browse/42/' - >>> c.build("kb/browse", dict()) - 'http://kb.example.com/browse/' - >>> c.build("kb/browse", dict(id=42, page=3)) - 'http://kb.example.com/browse/42/3' - >>> c.build("static/about") - '/about' - >>> c.build("static/index", force_external=True) - 'http://www.example.com/' - - >>> c = m.bind('example.com', subdomain='kb') - >>> c.build("static/about") - 'http://www.example.com/about' - - The first argument to bind is the server name *without* the subdomain. - Per default it will assume that the script is mounted on the root, but - often that's not the case so you can provide the real mount point as - second argument: - - >>> c = m.bind('example.com', '/applications/example') - - The third argument can be the subdomain, if not given the default - subdomain is used. For more details about binding have a look at the - documentation of the `MapAdapter`. - - And here is how you can match URLs: - - >>> c = m.bind('example.com') - >>> c.match("/") - ('static/index', {}) - >>> c.match("/about") - ('static/about', {}) - >>> c = m.bind('example.com', '/', 'kb') - >>> c.match("/") - ('kb/index', {}) - >>> c.match("/browse/42/23") - ('kb/browse', {'id': 42, 'page': 23}) - - If matching fails you get a `NotFound` exception, if the rule thinks - it's a good idea to redirect (for example because the URL was defined - to have a slash at the end but the request was missing that slash) it - will raise a `RequestRedirect` exception. Both are subclasses of the - `HTTPException` so you can use those errors as responses in the - application. - - If matching succeeded but the URL rule was incompatible to the given - method (for example there were only rules for `GET` and `HEAD` and - routing system tried to match a `POST` request) a `MethodNotAllowed` - exception is raised. - - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import ast -import difflib -import posixpath -import re -import uuid -import warnings -from pprint import pformat -from threading import Lock - -from ._compat import implements_to_string -from ._compat import iteritems -from ._compat import itervalues -from ._compat import native_string_result -from ._compat import string_types -from ._compat import text_type -from ._compat import to_bytes -from ._compat import to_unicode -from ._compat import wsgi_decoding_dance -from ._internal import _encode_idna -from ._internal import _get_environ -from .datastructures import ImmutableDict -from .datastructures import MultiDict -from .exceptions import BadHost -from .exceptions import BadRequest -from .exceptions import HTTPException -from .exceptions import MethodNotAllowed -from .exceptions import NotFound -from .urls import _fast_url_quote -from .urls import url_encode -from .urls import url_join -from .urls import url_quote -from .utils import cached_property -from .utils import format_string -from .utils import redirect -from .wsgi import get_host - -_rule_re = re.compile( - r""" - (?P[^<]*) # static rule data - < - (?: - (?P[a-zA-Z_][a-zA-Z0-9_]*) # converter name - (?:\((?P.*?)\))? # converter arguments - \: # variable delimiter - )? - (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name - > - """, - re.VERBOSE, -) -_simple_rule_re = re.compile(r"<([^>]+)>") -_converter_args_re = re.compile( - r""" - ((?P\w+)\s*=\s*)? - (?P - True|False| - \d+.\d+| - \d+.| - \d+| - [\w\d_.]+| - [urUR]?(?P"[^"]*?"|'[^']*') - )\s*, - """, - re.VERBOSE | re.UNICODE, -) - - -_PYTHON_CONSTANTS = {"None": None, "True": True, "False": False} - - -def _pythonize(value): - if value in _PYTHON_CONSTANTS: - return _PYTHON_CONSTANTS[value] - for convert in int, float: - try: - return convert(value) - except ValueError: - pass - if value[:1] == value[-1:] and value[0] in "\"'": - value = value[1:-1] - return text_type(value) - - -def parse_converter_args(argstr): - argstr += "," - args = [] - kwargs = {} - - for item in _converter_args_re.finditer(argstr): - value = item.group("stringval") - if value is None: - value = item.group("value") - value = _pythonize(value) - if not item.group("name"): - args.append(value) - else: - name = item.group("name") - kwargs[name] = value - - return tuple(args), kwargs - - -def parse_rule(rule): - """Parse a rule and return it as generator. Each iteration yields tuples - in the form ``(converter, arguments, variable)``. If the converter is - `None` it's a static url part, otherwise it's a dynamic one. - - :internal: - """ - pos = 0 - end = len(rule) - do_match = _rule_re.match - used_names = set() - while pos < end: - m = do_match(rule, pos) - if m is None: - break - data = m.groupdict() - if data["static"]: - yield None, None, data["static"] - variable = data["variable"] - converter = data["converter"] or "default" - if variable in used_names: - raise ValueError("variable name %r used twice." % variable) - used_names.add(variable) - yield converter, data["args"] or None, variable - pos = m.end() - if pos < end: - remaining = rule[pos:] - if ">" in remaining or "<" in remaining: - raise ValueError("malformed url rule: %r" % rule) - yield None, None, remaining - - -class RoutingException(Exception): - """Special exceptions that require the application to redirect, notifying - about missing urls, etc. - - :internal: - """ - - -class RequestRedirect(HTTPException, RoutingException): - """Raise if the map requests a redirect. This is for example the case if - `strict_slashes` are activated and an url that requires a trailing slash. - - The attribute `new_url` contains the absolute destination url. - """ - - code = 308 - - def __init__(self, new_url): - RoutingException.__init__(self, new_url) - self.new_url = new_url - - def get_response(self, environ=None): - return redirect(self.new_url, self.code) - - -class RequestPath(RoutingException): - """Internal exception.""" - - __slots__ = ("path_info",) - - def __init__(self, path_info): - self.path_info = path_info - - -class RequestAliasRedirect(RoutingException): # noqa: B903 - """This rule is an alias and wants to redirect to the canonical URL.""" - - def __init__(self, matched_values): - self.matched_values = matched_values - - -@implements_to_string -class BuildError(RoutingException, LookupError): - """Raised if the build system cannot find a URL for an endpoint with the - values provided. - """ - - def __init__(self, endpoint, values, method, adapter=None): - LookupError.__init__(self, endpoint, values, method) - self.endpoint = endpoint - self.values = values - self.method = method - self.adapter = adapter - - @cached_property - def suggested(self): - return self.closest_rule(self.adapter) - - def closest_rule(self, adapter): - def _score_rule(rule): - return sum( - [ - 0.98 - * difflib.SequenceMatcher( - None, rule.endpoint, self.endpoint - ).ratio(), - 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), - 0.01 * bool(rule.methods and self.method in rule.methods), - ] - ) - - if adapter and adapter.map._rules: - return max(adapter.map._rules, key=_score_rule) - - def __str__(self): - message = [] - message.append("Could not build url for endpoint %r" % self.endpoint) - if self.method: - message.append(" (%r)" % self.method) - if self.values: - message.append(" with values %r" % sorted(self.values.keys())) - message.append(".") - if self.suggested: - if self.endpoint == self.suggested.endpoint: - if self.method and self.method not in self.suggested.methods: - message.append( - " Did you mean to use methods %r?" - % sorted(self.suggested.methods) - ) - missing_values = self.suggested.arguments.union( - set(self.suggested.defaults or ()) - ) - set(self.values.keys()) - if missing_values: - message.append( - " Did you forget to specify values %r?" % sorted(missing_values) - ) - else: - message.append(" Did you mean %r instead?" % self.suggested.endpoint) - return u"".join(message) - - -class WebsocketMismatch(BadRequest): - """The only matched rule is either a WebSocket and the request is - HTTP, or the rule is HTTP and the request is a WebSocket. - """ - - -class ValidationError(ValueError): - """Validation error. If a rule converter raises this exception the rule - does not match the current URL and the next URL is tried. - """ - - -class RuleFactory(object): - """As soon as you have more complex URL setups it's a good idea to use rule - factories to avoid repetitive tasks. Some of them are builtin, others can - be added by subclassing `RuleFactory` and overriding `get_rules`. - """ - - def get_rules(self, map): - """Subclasses of `RuleFactory` have to override this method and return - an iterable of rules.""" - raise NotImplementedError() - - -class Subdomain(RuleFactory): - """All URLs provided by this factory have the subdomain set to a - specific domain. For example if you want to use the subdomain for - the current language this can be a good setup:: - - url_map = Map([ - Rule('/', endpoint='#select_language'), - Subdomain('', [ - Rule('/', endpoint='index'), - Rule('/about', endpoint='about'), - Rule('/help', endpoint='help') - ]) - ]) - - All the rules except for the ``'#select_language'`` endpoint will now - listen on a two letter long subdomain that holds the language code - for the current request. - """ - - def __init__(self, subdomain, rules): - self.subdomain = subdomain - self.rules = rules - - def get_rules(self, map): - for rulefactory in self.rules: - for rule in rulefactory.get_rules(map): - rule = rule.empty() - rule.subdomain = self.subdomain - yield rule - - -class Submount(RuleFactory): - """Like `Subdomain` but prefixes the URL rule with a given string:: - - url_map = Map([ - Rule('/', endpoint='index'), - Submount('/blog', [ - Rule('/', endpoint='blog/index'), - Rule('/entry/', endpoint='blog/show') - ]) - ]) - - Now the rule ``'blog/show'`` matches ``/blog/entry/``. - """ - - def __init__(self, path, rules): - self.path = path.rstrip("/") - self.rules = rules - - def get_rules(self, map): - for rulefactory in self.rules: - for rule in rulefactory.get_rules(map): - rule = rule.empty() - rule.rule = self.path + rule.rule - yield rule - - -class EndpointPrefix(RuleFactory): - """Prefixes all endpoints (which must be strings for this factory) with - another string. This can be useful for sub applications:: - - url_map = Map([ - Rule('/', endpoint='index'), - EndpointPrefix('blog/', [Submount('/blog', [ - Rule('/', endpoint='index'), - Rule('/entry/', endpoint='show') - ])]) - ]) - """ - - def __init__(self, prefix, rules): - self.prefix = prefix - self.rules = rules - - def get_rules(self, map): - for rulefactory in self.rules: - for rule in rulefactory.get_rules(map): - rule = rule.empty() - rule.endpoint = self.prefix + rule.endpoint - yield rule - - -class RuleTemplate(object): - """Returns copies of the rules wrapped and expands string templates in - the endpoint, rule, defaults or subdomain sections. - - Here a small example for such a rule template:: - - from werkzeug.routing import Map, Rule, RuleTemplate - - resource = RuleTemplate([ - Rule('/$name/', endpoint='$name.list'), - Rule('/$name/', endpoint='$name.show') - ]) - - url_map = Map([resource(name='user'), resource(name='page')]) - - When a rule template is called the keyword arguments are used to - replace the placeholders in all the string parameters. - """ - - def __init__(self, rules): - self.rules = list(rules) - - def __call__(self, *args, **kwargs): - return RuleTemplateFactory(self.rules, dict(*args, **kwargs)) - - -class RuleTemplateFactory(RuleFactory): - """A factory that fills in template variables into rules. Used by - `RuleTemplate` internally. - - :internal: - """ - - def __init__(self, rules, context): - self.rules = rules - self.context = context - - def get_rules(self, map): - for rulefactory in self.rules: - for rule in rulefactory.get_rules(map): - new_defaults = subdomain = None - if rule.defaults: - new_defaults = {} - for key, value in iteritems(rule.defaults): - if isinstance(value, string_types): - value = format_string(value, self.context) - new_defaults[key] = value - if rule.subdomain is not None: - subdomain = format_string(rule.subdomain, self.context) - new_endpoint = rule.endpoint - if isinstance(new_endpoint, string_types): - new_endpoint = format_string(new_endpoint, self.context) - yield Rule( - format_string(rule.rule, self.context), - new_defaults, - subdomain, - rule.methods, - rule.build_only, - new_endpoint, - rule.strict_slashes, - ) - - -def _prefix_names(src): - """ast parse and prefix names with `.` to avoid collision with user vars""" - tree = ast.parse(src).body[0] - if isinstance(tree, ast.Expr): - tree = tree.value - for node in ast.walk(tree): - if isinstance(node, ast.Name): - node.id = "." + node.id - return tree - - -_CALL_CONVERTER_CODE_FMT = "self._converters[{elem!r}].to_url()" -_IF_KWARGS_URL_ENCODE_CODE = """\ -if kwargs: - q = '?' - params = self._encode_query_vars(kwargs) -else: - q = params = '' -""" -_IF_KWARGS_URL_ENCODE_AST = _prefix_names(_IF_KWARGS_URL_ENCODE_CODE) -_URL_ENCODE_AST_NAMES = (_prefix_names("q"), _prefix_names("params")) - - -@implements_to_string -class Rule(RuleFactory): - """A Rule represents one URL pattern. There are some options for `Rule` - that change the way it behaves and are passed to the `Rule` constructor. - Note that besides the rule-string all arguments *must* be keyword arguments - in order to not break the application on Werkzeug upgrades. - - `string` - Rule strings basically are just normal URL paths with placeholders in - the format ```` where the converter and the - arguments are optional. If no converter is defined the `default` - converter is used which means `string` in the normal configuration. - - URL rules that end with a slash are branch URLs, others are leaves. - If you have `strict_slashes` enabled (which is the default), all - branch URLs that are matched without a trailing slash will trigger a - redirect to the same URL with the missing slash appended. - - The converters are defined on the `Map`. - - `endpoint` - The endpoint for this rule. This can be anything. A reference to a - function, a string, a number etc. The preferred way is using a string - because the endpoint is used for URL generation. - - `defaults` - An optional dict with defaults for other rules with the same endpoint. - This is a bit tricky but useful if you want to have unique URLs:: - - url_map = Map([ - Rule('/all/', defaults={'page': 1}, endpoint='all_entries'), - Rule('/all/page/', endpoint='all_entries') - ]) - - If a user now visits ``http://example.com/all/page/1`` he will be - redirected to ``http://example.com/all/``. If `redirect_defaults` is - disabled on the `Map` instance this will only affect the URL - generation. - - `subdomain` - The subdomain rule string for this rule. If not specified the rule - only matches for the `default_subdomain` of the map. If the map is - not bound to a subdomain this feature is disabled. - - Can be useful if you want to have user profiles on different subdomains - and all subdomains are forwarded to your application:: - - url_map = Map([ - Rule('/', subdomain='', endpoint='user/homepage'), - Rule('/stats', subdomain='', endpoint='user/stats') - ]) - - `methods` - A sequence of http methods this rule applies to. If not specified, all - methods are allowed. For example this can be useful if you want different - endpoints for `POST` and `GET`. If methods are defined and the path - matches but the method matched against is not in this list or in the - list of another rule for that path the error raised is of the type - `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the - list of methods and `HEAD` is not, `HEAD` is added automatically. - - `strict_slashes` - Override the `Map` setting for `strict_slashes` only for this rule. If - not specified the `Map` setting is used. - - `merge_slashes` - Override :attr:`Map.merge_slashes` for this rule. - - `build_only` - Set this to True and the rule will never match but will create a URL - that can be build. This is useful if you have resources on a subdomain - or folder that are not handled by the WSGI application (like static data) - - `redirect_to` - If given this must be either a string or callable. In case of a - callable it's called with the url adapter that triggered the match and - the values of the URL as keyword arguments and has to return the target - for the redirect, otherwise it has to be a string with placeholders in - rule syntax:: - - def foo_with_slug(adapter, id): - # ask the database for the slug for the old id. this of - # course has nothing to do with werkzeug. - return 'foo/' + Foo.get_slug_for_id(id) - - url_map = Map([ - Rule('/foo/', endpoint='foo'), - Rule('/some/old/url/', redirect_to='foo/'), - Rule('/other/old/url/', redirect_to=foo_with_slug) - ]) - - When the rule is matched the routing system will raise a - `RequestRedirect` exception with the target for the redirect. - - Keep in mind that the URL will be joined against the URL root of the - script so don't use a leading slash on the target URL unless you - really mean root of that domain. - - `alias` - If enabled this rule serves as an alias for another rule with the same - endpoint and arguments. - - `host` - If provided and the URL map has host matching enabled this can be - used to provide a match rule for the whole host. This also means - that the subdomain feature is disabled. - - `websocket` - If ``True``, this rule is only matches for WebSocket (``ws://``, - ``wss://``) requests. By default, rules will only match for HTTP - requests. - - .. versionadded:: 1.0 - Added ``websocket``. - - .. versionadded:: 1.0 - Added ``merge_slashes``. - - .. versionadded:: 0.7 - Added ``alias`` and ``host``. - - .. versionchanged:: 0.6.1 - ``HEAD`` is added to ``methods`` if ``GET`` is present. - """ - - def __init__( - self, - string, - defaults=None, - subdomain=None, - methods=None, - build_only=False, - endpoint=None, - strict_slashes=None, - merge_slashes=None, - redirect_to=None, - alias=False, - host=None, - websocket=False, - ): - if not string.startswith("/"): - raise ValueError("urls must start with a leading slash") - self.rule = string - self.is_leaf = not string.endswith("/") - - self.map = None - self.strict_slashes = strict_slashes - self.merge_slashes = merge_slashes - self.subdomain = subdomain - self.host = host - self.defaults = defaults - self.build_only = build_only - self.alias = alias - self.websocket = websocket - - if methods is not None: - if isinstance(methods, str): - raise TypeError("'methods' should be a list of strings.") - - methods = {x.upper() for x in methods} - - if "HEAD" not in methods and "GET" in methods: - methods.add("HEAD") - - if websocket and methods - {"GET", "HEAD", "OPTIONS"}: - raise ValueError( - "WebSocket rules can only use 'GET', 'HEAD', and 'OPTIONS' methods." - ) - - self.methods = methods - self.endpoint = endpoint - self.redirect_to = redirect_to - - if defaults: - self.arguments = set(map(str, defaults)) - else: - self.arguments = set() - self._trace = self._converters = self._regex = self._argument_weights = None - - def empty(self): - """ - Return an unbound copy of this rule. - - This can be useful if want to reuse an already bound URL for another - map. See ``get_empty_kwargs`` to override what keyword arguments are - provided to the new copy. - """ - return type(self)(self.rule, **self.get_empty_kwargs()) - - def get_empty_kwargs(self): - """ - Provides kwargs for instantiating empty copy with empty() - - Use this method to provide custom keyword arguments to the subclass of - ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass - has custom keyword arguments that are needed at instantiation. - - Must return a ``dict`` that will be provided as kwargs to the new - instance of ``Rule``, following the initial ``self.rule`` value which - is always provided as the first, required positional argument. - """ - defaults = None - if self.defaults: - defaults = dict(self.defaults) - return dict( - defaults=defaults, - subdomain=self.subdomain, - methods=self.methods, - build_only=self.build_only, - endpoint=self.endpoint, - strict_slashes=self.strict_slashes, - redirect_to=self.redirect_to, - alias=self.alias, - host=self.host, - ) - - def get_rules(self, map): - yield self - - def refresh(self): - """Rebinds and refreshes the URL. Call this if you modified the - rule in place. - - :internal: - """ - self.bind(self.map, rebind=True) - - def bind(self, map, rebind=False): - """Bind the url to a map and create a regular expression based on - the information from the rule itself and the defaults from the map. - - :internal: - """ - if self.map is not None and not rebind: - raise RuntimeError("url rule %r already bound to map %r" % (self, self.map)) - self.map = map - if self.strict_slashes is None: - self.strict_slashes = map.strict_slashes - if self.merge_slashes is None: - self.merge_slashes = map.merge_slashes - if self.subdomain is None: - self.subdomain = map.default_subdomain - self.compile() - - def get_converter(self, variable_name, converter_name, args, kwargs): - """Looks up the converter for the given parameter. - - .. versionadded:: 0.9 - """ - if converter_name not in self.map.converters: - raise LookupError("the converter %r does not exist" % converter_name) - return self.map.converters[converter_name](self.map, *args, **kwargs) - - def _encode_query_vars(self, query_vars): - return url_encode( - query_vars, - charset=self.map.charset, - sort=self.map.sort_parameters, - key=self.map.sort_key, - ) - - def compile(self): - """Compiles the regular expression and stores it.""" - assert self.map is not None, "rule not bound" - - if self.map.host_matching: - domain_rule = self.host or "" - else: - domain_rule = self.subdomain or "" - - self._trace = [] - self._converters = {} - self._static_weights = [] - self._argument_weights = [] - regex_parts = [] - - def _build_regex(rule): - index = 0 - for converter, arguments, variable in parse_rule(rule): - if converter is None: - for match in re.finditer(r"/+|[^/]+", variable): - part = match.group(0) - if part.startswith("/"): - if self.merge_slashes: - regex_parts.append(r"/+?") - self._trace.append((False, "/")) - else: - regex_parts.append(part) - self._trace.append((False, part)) - continue - self._trace.append((False, part)) - regex_parts.append(re.escape(part)) - if part: - self._static_weights.append((index, -len(part))) - else: - if arguments: - c_args, c_kwargs = parse_converter_args(arguments) - else: - c_args = () - c_kwargs = {} - convobj = self.get_converter(variable, converter, c_args, c_kwargs) - regex_parts.append("(?P<%s>%s)" % (variable, convobj.regex)) - self._converters[variable] = convobj - self._trace.append((True, variable)) - self._argument_weights.append(convobj.weight) - self.arguments.add(str(variable)) - index = index + 1 - - _build_regex(domain_rule) - regex_parts.append("\\|") - self._trace.append((False, "|")) - _build_regex(self.rule if self.is_leaf else self.rule.rstrip("/")) - if not self.is_leaf: - self._trace.append((False, "/")) - - self._build = self._compile_builder(False).__get__(self, None) - self._build_unknown = self._compile_builder(True).__get__(self, None) - - if self.build_only: - return - - if not (self.is_leaf and self.strict_slashes): - reps = u"*" if self.merge_slashes else u"?" - tail = u"(?/%s)" % reps - else: - tail = u"" - - regex = u"^%s%s$" % (u"".join(regex_parts), tail) - self._regex = re.compile(regex, re.UNICODE) - - def match(self, path, method=None): - """Check if the rule matches a given path. Path is a string in the - form ``"subdomain|/path"`` and is assembled by the map. If - the map is doing host matching the subdomain part will be the host - instead. - - If the rule matches a dict with the converted values is returned, - otherwise the return value is `None`. - - :internal: - """ - if not self.build_only: - require_redirect = False - - m = self._regex.search(path) - if m is not None: - groups = m.groupdict() - # we have a folder like part of the url without a trailing - # slash and strict slashes enabled. raise an exception that - # tells the map to redirect to the same url but with a - # trailing slash - if ( - self.strict_slashes - and not self.is_leaf - and not groups.pop("__suffix__") - and ( - method is None or self.methods is None or method in self.methods - ) - ): - path += "/" - require_redirect = True - # if we are not in strict slashes mode we have to remove - # a __suffix__ - elif not self.strict_slashes: - del groups["__suffix__"] - - result = {} - for name, value in iteritems(groups): - try: - value = self._converters[name].to_python(value) - except ValidationError: - return - result[str(name)] = value - if self.defaults: - result.update(self.defaults) - - if self.merge_slashes: - new_path = "|".join(self.build(result, False)) - if path.endswith("/") and not new_path.endswith("/"): - new_path += "/" - if new_path.count("/") < path.count("/"): - path = new_path - require_redirect = True - - if require_redirect: - path = path.split("|", 1)[1] - raise RequestPath(path) - - if self.alias and self.map.redirect_defaults: - raise RequestAliasRedirect(result) - - return result - - @staticmethod - def _get_func_code(code, name): - globs, locs = {}, {} - exec(code, globs, locs) - return locs[name] - - def _compile_builder(self, append_unknown=True): - defaults = self.defaults or {} - dom_ops = [] - url_ops = [] - - opl = dom_ops - for is_dynamic, data in self._trace: - if data == "|" and opl is dom_ops: - opl = url_ops - continue - # this seems like a silly case to ever come up but: - # if a default is given for a value that appears in the rule, - # resolve it to a constant ahead of time - if is_dynamic and data in defaults: - data = self._converters[data].to_url(defaults[data]) - opl.append((False, data)) - elif not is_dynamic: - opl.append( - (False, url_quote(to_bytes(data, self.map.charset), safe="/:|+")) - ) - else: - opl.append((True, data)) - - def _convert(elem): - ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem)) - ret.args = [ast.Name(str(elem), ast.Load())] # str for py2 - return ret - - def _parts(ops): - parts = [ - _convert(elem) if is_dynamic else ast.Str(s=elem) - for is_dynamic, elem in ops - ] - parts = parts or [ast.Str("")] - # constant fold - ret = [parts[0]] - for p in parts[1:]: - if isinstance(p, ast.Str) and isinstance(ret[-1], ast.Str): - ret[-1] = ast.Str(ret[-1].s + p.s) - else: - ret.append(p) - return ret - - dom_parts = _parts(dom_ops) - url_parts = _parts(url_ops) - if not append_unknown: - body = [] - else: - body = [_IF_KWARGS_URL_ENCODE_AST] - url_parts.extend(_URL_ENCODE_AST_NAMES) - - def _join(parts): - if len(parts) == 1: # shortcut - return parts[0] - elif hasattr(ast, "JoinedStr"): # py36+ - return ast.JoinedStr(parts) - else: - call = _prefix_names('"".join()') - call.args = [ast.Tuple(parts, ast.Load())] - return call - - body.append( - ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())) - ) - - # str is necessary for python2 - pargs = [ - str(elem) - for is_dynamic, elem in dom_ops + url_ops - if is_dynamic and elem not in defaults - ] - kargs = [str(k) for k in defaults] - - func_ast = _prefix_names("def _(): pass") - func_ast.name = "".format(self.rule) - if hasattr(ast, "arg"): # py3 - func_ast.args.args.append(ast.arg(".self", None)) - for arg in pargs + kargs: - func_ast.args.args.append(ast.arg(arg, None)) - func_ast.args.kwarg = ast.arg(".kwargs", None) - else: - func_ast.args.args.append(ast.Name(".self", ast.Param())) - for arg in pargs + kargs: - func_ast.args.args.append(ast.Name(arg, ast.Param())) - func_ast.args.kwarg = ".kwargs" - for _ in kargs: - func_ast.args.defaults.append(ast.Str("")) - func_ast.body = body - - # use `ast.parse` instead of `ast.Module` for better portability - # python3.8 changes the signature of `ast.Module` - module = ast.parse("") - module.body = [func_ast] - - # mark everything as on line 1, offset 0 - # less error-prone than `ast.fix_missing_locations` - # bad line numbers cause an assert to fail in debug builds - for node in ast.walk(module): - if "lineno" in node._attributes: - node.lineno = 1 - if "col_offset" in node._attributes: - node.col_offset = 0 - - code = compile(module, "", "exec") - return self._get_func_code(code, func_ast.name) - - def build(self, values, append_unknown=True): - """Assembles the relative url for that rule and the subdomain. - If building doesn't work for some reasons `None` is returned. - - :internal: - """ - try: - if append_unknown: - return self._build_unknown(**values) - else: - return self._build(**values) - except ValidationError: - return None - - def provides_defaults_for(self, rule): - """Check if this rule has defaults for a given rule. - - :internal: - """ - return ( - not self.build_only - and self.defaults - and self.endpoint == rule.endpoint - and self != rule - and self.arguments == rule.arguments - ) - - def suitable_for(self, values, method=None): - """Check if the dict of values has enough data for url generation. - - :internal: - """ - # if a method was given explicitly and that method is not supported - # by this rule, this rule is not suitable. - if ( - method is not None - and self.methods is not None - and method not in self.methods - ): - return False - - defaults = self.defaults or () - - # all arguments required must be either in the defaults dict or - # the value dictionary otherwise it's not suitable - for key in self.arguments: - if key not in defaults and key not in values: - return False - - # in case defaults are given we ensure that either the value was - # skipped or the value is the same as the default value. - if defaults: - for key, value in iteritems(defaults): - if key in values and value != values[key]: - return False - - return True - - def match_compare_key(self): - """The match compare key for sorting. - - Current implementation: - - 1. rules without any arguments come first for performance - reasons only as we expect them to match faster and some - common ones usually don't have any arguments (index pages etc.) - 2. rules with more static parts come first so the second argument - is the negative length of the number of the static weights. - 3. we order by static weights, which is a combination of index - and length - 4. The more complex rules come first so the next argument is the - negative length of the number of argument weights. - 5. lastly we order by the actual argument weights. - - :internal: - """ - return ( - bool(self.arguments), - -len(self._static_weights), - self._static_weights, - -len(self._argument_weights), - self._argument_weights, - ) - - def build_compare_key(self): - """The build compare key for sorting. - - :internal: - """ - return 1 if self.alias else 0, -len(self.arguments), -len(self.defaults or ()) - - def __eq__(self, other): - return self.__class__ is other.__class__ and self._trace == other._trace - - __hash__ = None - - def __ne__(self, other): - return not self.__eq__(other) - - def __str__(self): - return self.rule - - @native_string_result - def __repr__(self): - if self.map is None: - return u"<%s (unbound)>" % self.__class__.__name__ - tmp = [] - for is_dynamic, data in self._trace: - if is_dynamic: - tmp.append(u"<%s>" % data) - else: - tmp.append(data) - return u"<%s %s%s -> %s>" % ( - self.__class__.__name__, - repr((u"".join(tmp)).lstrip(u"|")).lstrip(u"u"), - self.methods is not None and u" (%s)" % u", ".join(self.methods) or u"", - self.endpoint, - ) - - -class BaseConverter(object): - """Base class for all converters.""" - - regex = "[^/]+" - weight = 100 - - def __init__(self, map): - self.map = map - - def to_python(self, value): - return value - - def to_url(self, value): - if isinstance(value, (bytes, bytearray)): - return _fast_url_quote(value) - return _fast_url_quote(text_type(value).encode(self.map.charset)) - - -class UnicodeConverter(BaseConverter): - """This converter is the default converter and accepts any string but - only one path segment. Thus the string can not include a slash. - - This is the default validator. - - Example:: - - Rule('/pages/'), - Rule('/') - - :param map: the :class:`Map`. - :param minlength: the minimum length of the string. Must be greater - or equal 1. - :param maxlength: the maximum length of the string. - :param length: the exact length of the string. - """ - - def __init__(self, map, minlength=1, maxlength=None, length=None): - BaseConverter.__init__(self, map) - if length is not None: - length = "{%d}" % int(length) - else: - if maxlength is None: - maxlength = "" - else: - maxlength = int(maxlength) - length = "{%s,%s}" % (int(minlength), maxlength) - self.regex = "[^/]" + length - - -class AnyConverter(BaseConverter): - """Matches one of the items provided. Items can either be Python - identifiers or strings:: - - Rule('/') - - :param map: the :class:`Map`. - :param items: this function accepts the possible items as positional - arguments. - """ - - def __init__(self, map, *items): - BaseConverter.__init__(self, map) - self.regex = "(?:%s)" % "|".join([re.escape(x) for x in items]) - - -class PathConverter(BaseConverter): - """Like the default :class:`UnicodeConverter`, but it also matches - slashes. This is useful for wikis and similar applications:: - - Rule('/') - Rule('//edit') - - :param map: the :class:`Map`. - """ - - regex = "[^/].*?" - weight = 200 - - -class NumberConverter(BaseConverter): - """Baseclass for `IntegerConverter` and `FloatConverter`. - - :internal: - """ - - weight = 50 - - def __init__(self, map, fixed_digits=0, min=None, max=None, signed=False): - if signed: - self.regex = self.signed_regex - BaseConverter.__init__(self, map) - self.fixed_digits = fixed_digits - self.min = min - self.max = max - self.signed = signed - - def to_python(self, value): - if self.fixed_digits and len(value) != self.fixed_digits: - raise ValidationError() - value = self.num_convert(value) - if (self.min is not None and value < self.min) or ( - self.max is not None and value > self.max - ): - raise ValidationError() - return value - - def to_url(self, value): - value = self.num_convert(value) - if self.fixed_digits: - value = ("%%0%sd" % self.fixed_digits) % value - return str(value) - - @property - def signed_regex(self): - return r"-?" + self.regex - - -class IntegerConverter(NumberConverter): - """This converter only accepts integer values:: - - Rule("/page/") - - By default it only accepts unsigned, positive values. The ``signed`` - parameter will enable signed, negative values. :: - - Rule("/page/") - - :param map: The :class:`Map`. - :param fixed_digits: The number of fixed digits in the URL. If you - set this to ``4`` for example, the rule will only match if the - URL looks like ``/0001/``. The default is variable length. - :param min: The minimal value. - :param max: The maximal value. - :param signed: Allow signed (negative) values. - - .. versionadded:: 0.15 - The ``signed`` parameter. - """ - - regex = r"\d+" - num_convert = int - - -class FloatConverter(NumberConverter): - """This converter only accepts floating point values:: - - Rule("/probability/") - - By default it only accepts unsigned, positive values. The ``signed`` - parameter will enable signed, negative values. :: - - Rule("/offset/") - - :param map: The :class:`Map`. - :param min: The minimal value. - :param max: The maximal value. - :param signed: Allow signed (negative) values. - - .. versionadded:: 0.15 - The ``signed`` parameter. - """ - - regex = r"\d+\.\d+" - num_convert = float - - def __init__(self, map, min=None, max=None, signed=False): - NumberConverter.__init__(self, map, min=min, max=max, signed=signed) - - -class UUIDConverter(BaseConverter): - """This converter only accepts UUID strings:: - - Rule('/object/') - - .. versionadded:: 0.10 - - :param map: the :class:`Map`. - """ - - regex = ( - r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-" - r"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" - ) - - def to_python(self, value): - return uuid.UUID(value) - - def to_url(self, value): - return str(value) - - -#: the default converter mapping for the map. -DEFAULT_CONVERTERS = { - "default": UnicodeConverter, - "string": UnicodeConverter, - "any": AnyConverter, - "path": PathConverter, - "int": IntegerConverter, - "float": FloatConverter, - "uuid": UUIDConverter, -} - - -class Map(object): - """The map class stores all the URL rules and some configuration - parameters. Some of the configuration values are only stored on the - `Map` instance since those affect all rules, others are just defaults - and can be overridden for each rule. Note that you have to specify all - arguments besides the `rules` as keyword arguments! - - :param rules: sequence of url rules for this map. - :param default_subdomain: The default subdomain for rules without a - subdomain defined. - :param charset: charset of the url. defaults to ``"utf-8"`` - :param strict_slashes: If a rule ends with a slash but the matched - URL does not, redirect to the URL with a trailing slash. - :param merge_slashes: Merge consecutive slashes when matching or - building URLs. Matches will redirect to the normalized URL. - Slashes in variable parts are not merged. - :param redirect_defaults: This will redirect to the default rule if it - wasn't visited that way. This helps creating - unique URLs. - :param converters: A dict of converters that adds additional converters - to the list of converters. If you redefine one - converter this will override the original one. - :param sort_parameters: If set to `True` the url parameters are sorted. - See `url_encode` for more details. - :param sort_key: The sort key function for `url_encode`. - :param encoding_errors: the error method to use for decoding - :param host_matching: if set to `True` it enables the host matching - feature and disables the subdomain one. If - enabled the `host` parameter to rules is used - instead of the `subdomain` one. - - .. versionchanged:: 1.0 - If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules - will match. - - .. versionchanged:: 1.0 - Added ``merge_slashes``. - - .. versionchanged:: 0.7 - Added ``encoding_errors`` and ``host_matching``. - - .. versionchanged:: 0.5 - Added ``sort_parameters`` and ``sort_key``. - """ - - #: A dict of default converters to be used. - default_converters = ImmutableDict(DEFAULT_CONVERTERS) - - #: The type of lock to use when updating. - #: - #: .. versionadded:: 1.0 - lock_class = Lock - - def __init__( - self, - rules=None, - default_subdomain="", - charset="utf-8", - strict_slashes=True, - merge_slashes=True, - redirect_defaults=True, - converters=None, - sort_parameters=False, - sort_key=None, - encoding_errors="replace", - host_matching=False, - ): - self._rules = [] - self._rules_by_endpoint = {} - self._remap = True - self._remap_lock = self.lock_class() - - self.default_subdomain = default_subdomain - self.charset = charset - self.encoding_errors = encoding_errors - self.strict_slashes = strict_slashes - self.merge_slashes = merge_slashes - self.redirect_defaults = redirect_defaults - self.host_matching = host_matching - - self.converters = self.default_converters.copy() - if converters: - self.converters.update(converters) - - self.sort_parameters = sort_parameters - self.sort_key = sort_key - - for rulefactory in rules or (): - self.add(rulefactory) - - def is_endpoint_expecting(self, endpoint, *arguments): - """Iterate over all rules and check if the endpoint expects - the arguments provided. This is for example useful if you have - some URLs that expect a language code and others that do not and - you want to wrap the builder a bit so that the current language - code is automatically added if not provided but endpoints expect - it. - - :param endpoint: the endpoint to check. - :param arguments: this function accepts one or more arguments - as positional arguments. Each one of them is - checked. - """ - self.update() - arguments = set(arguments) - for rule in self._rules_by_endpoint[endpoint]: - if arguments.issubset(rule.arguments): - return True - return False - - def iter_rules(self, endpoint=None): - """Iterate over all rules or the rules of an endpoint. - - :param endpoint: if provided only the rules for that endpoint - are returned. - :return: an iterator - """ - self.update() - if endpoint is not None: - return iter(self._rules_by_endpoint[endpoint]) - return iter(self._rules) - - def add(self, rulefactory): - """Add a new rule or factory to the map and bind it. Requires that the - rule is not bound to another map. - - :param rulefactory: a :class:`Rule` or :class:`RuleFactory` - """ - for rule in rulefactory.get_rules(self): - rule.bind(self) - self._rules.append(rule) - self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule) - self._remap = True - - def bind( - self, - server_name, - script_name=None, - subdomain=None, - url_scheme="http", - default_method="GET", - path_info=None, - query_args=None, - ): - """Return a new :class:`MapAdapter` with the details specified to the - call. Note that `script_name` will default to ``'/'`` if not further - specified or `None`. The `server_name` at least is a requirement - because the HTTP RFC requires absolute URLs for redirects and so all - redirect exceptions raised by Werkzeug will contain the full canonical - URL. - - If no path_info is passed to :meth:`match` it will use the default path - info passed to bind. While this doesn't really make sense for - manual bind calls, it's useful if you bind a map to a WSGI - environment which already contains the path info. - - `subdomain` will default to the `default_subdomain` for this map if - no defined. If there is no `default_subdomain` you cannot use the - subdomain feature. - - .. versionchanged:: 1.0 - If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules - will match. - - .. versionchanged:: 0.15 - ``path_info`` defaults to ``'/'`` if ``None``. - - .. versionchanged:: 0.8 - ``query_args`` can be a string. - - .. versionchanged:: 0.7 - Added ``query_args``. - """ - server_name = server_name.lower() - if self.host_matching: - if subdomain is not None: - raise RuntimeError("host matching enabled and a subdomain was provided") - elif subdomain is None: - subdomain = self.default_subdomain - if script_name is None: - script_name = "/" - if path_info is None: - path_info = "/" - try: - server_name = _encode_idna(server_name) - except UnicodeError: - raise BadHost() - return MapAdapter( - self, - server_name, - script_name, - subdomain, - url_scheme, - path_info, - default_method, - query_args, - ) - - def bind_to_environ(self, environ, server_name=None, subdomain=None): - """Like :meth:`bind` but you can pass it an WSGI environment and it - will fetch the information from that dictionary. Note that because of - limitations in the protocol there is no way to get the current - subdomain and real `server_name` from the environment. If you don't - provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or - `HTTP_HOST` if provided) as used `server_name` with disabled subdomain - feature. - - If `subdomain` is `None` but an environment and a server name is - provided it will calculate the current subdomain automatically. - Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` - in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated - subdomain will be ``'staging.dev'``. - - If the object passed as environ has an environ attribute, the value of - this attribute is used instead. This allows you to pass request - objects. Additionally `PATH_INFO` added as a default of the - :class:`MapAdapter` so that you don't have to pass the path info to - the match method. - - .. versionchanged:: 1.0.0 - If the passed server name specifies port 443, it will match - if the incoming scheme is ``https`` without a port. - - .. versionchanged:: 1.0.0 - A warning is shown when the passed server name does not - match the incoming WSGI server name. - - .. versionchanged:: 0.8 - This will no longer raise a ValueError when an unexpected server - name was passed. - - .. versionchanged:: 0.5 - previously this method accepted a bogus `calculate_subdomain` - parameter that did not have any effect. It was removed because - of that. - - :param environ: a WSGI environment. - :param server_name: an optional server name hint (see above). - :param subdomain: optionally the current subdomain (see above). - """ - environ = _get_environ(environ) - wsgi_server_name = get_host(environ).lower() - scheme = environ["wsgi.url_scheme"] - - if server_name is None: - server_name = wsgi_server_name - else: - server_name = server_name.lower() - - # strip standard port to match get_host() - if scheme == "http" and server_name.endswith(":80"): - server_name = server_name[:-3] - elif scheme == "https" and server_name.endswith(":443"): - server_name = server_name[:-4] - - if subdomain is None and not self.host_matching: - cur_server_name = wsgi_server_name.split(".") - real_server_name = server_name.split(".") - offset = -len(real_server_name) - - if cur_server_name[offset:] != real_server_name: - # This can happen even with valid configs if the server was - # accessed directly by IP address under some situations. - # Instead of raising an exception like in Werkzeug 0.7 or - # earlier we go by an invalid subdomain which will result - # in a 404 error on matching. - warnings.warn( - "Current server name '{}' doesn't match configured" - " server name '{}'".format(wsgi_server_name, server_name), - stacklevel=2, - ) - subdomain = "" - else: - subdomain = ".".join(filter(None, cur_server_name[:offset])) - - def _get_wsgi_string(name): - val = environ.get(name) - if val is not None: - return wsgi_decoding_dance(val, self.charset) - - script_name = _get_wsgi_string("SCRIPT_NAME") - path_info = _get_wsgi_string("PATH_INFO") - query_args = _get_wsgi_string("QUERY_STRING") - return Map.bind( - self, - server_name, - script_name, - subdomain, - scheme, - environ["REQUEST_METHOD"], - path_info, - query_args=query_args, - ) - - def update(self): - """Called before matching and building to keep the compiled rules - in the correct order after things changed. - """ - if not self._remap: - return - - with self._remap_lock: - if not self._remap: - return - - self._rules.sort(key=lambda x: x.match_compare_key()) - for rules in itervalues(self._rules_by_endpoint): - rules.sort(key=lambda x: x.build_compare_key()) - self._remap = False - - def __repr__(self): - rules = self.iter_rules() - return "%s(%s)" % (self.__class__.__name__, pformat(list(rules))) - - -class MapAdapter(object): - - """Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does - the URL matching and building based on runtime information. - """ - - def __init__( - self, - map, - server_name, - script_name, - subdomain, - url_scheme, - path_info, - default_method, - query_args=None, - ): - self.map = map - self.server_name = to_unicode(server_name) - script_name = to_unicode(script_name) - if not script_name.endswith(u"/"): - script_name += u"/" - self.script_name = script_name - self.subdomain = to_unicode(subdomain) - self.url_scheme = to_unicode(url_scheme) - self.path_info = to_unicode(path_info) - self.default_method = to_unicode(default_method) - self.query_args = query_args - self.websocket = self.url_scheme in {"ws", "wss"} - - def dispatch( - self, view_func, path_info=None, method=None, catch_http_exceptions=False - ): - """Does the complete dispatching process. `view_func` is called with - the endpoint and a dict with the values for the view. It should - look up the view function, call it, and return a response object - or WSGI application. http exceptions are not caught by default - so that applications can display nicer error messages by just - catching them by hand. If you want to stick with the default - error messages you can pass it ``catch_http_exceptions=True`` and - it will catch the http exceptions. - - Here a small example for the dispatch usage:: - - from werkzeug.wrappers import Request, Response - from werkzeug.wsgi import responder - from werkzeug.routing import Map, Rule - - def on_index(request): - return Response('Hello from the index') - - url_map = Map([Rule('/', endpoint='index')]) - views = {'index': on_index} - - @responder - def application(environ, start_response): - request = Request(environ) - urls = url_map.bind_to_environ(environ) - return urls.dispatch(lambda e, v: views[e](request, **v), - catch_http_exceptions=True) - - Keep in mind that this method might return exception objects, too, so - use :class:`Response.force_type` to get a response object. - - :param view_func: a function that is called with the endpoint as - first argument and the value dict as second. Has - to dispatch to the actual view function with this - information. (see above) - :param path_info: the path info to use for matching. Overrides the - path info specified on binding. - :param method: the HTTP method used for matching. Overrides the - method specified on binding. - :param catch_http_exceptions: set to `True` to catch any of the - werkzeug :class:`HTTPException`\\s. - """ - try: - try: - endpoint, args = self.match(path_info, method) - except RequestRedirect as e: - return e - return view_func(endpoint, args) - except HTTPException as e: - if catch_http_exceptions: - return e - raise - - def match( - self, - path_info=None, - method=None, - return_rule=False, - query_args=None, - websocket=None, - ): - """The usage is simple: you just pass the match method the current - path info as well as the method (which defaults to `GET`). The - following things can then happen: - - - you receive a `NotFound` exception that indicates that no URL is - matching. A `NotFound` exception is also a WSGI application you - can call to get a default page not found page (happens to be the - same object as `werkzeug.exceptions.NotFound`) - - - you receive a `MethodNotAllowed` exception that indicates that there - is a match for this URL but not for the current request method. - This is useful for RESTful applications. - - - you receive a `RequestRedirect` exception with a `new_url` - attribute. This exception is used to notify you about a request - Werkzeug requests from your WSGI application. This is for example the - case if you request ``/foo`` although the correct URL is ``/foo/`` - You can use the `RequestRedirect` instance as response-like object - similar to all other subclasses of `HTTPException`. - - - you receive a ``WebsocketMismatch`` exception if the only - match is a WebSocket rule but the bind is an HTTP request, or - if the match is an HTTP rule but the bind is a WebSocket - request. - - - you get a tuple in the form ``(endpoint, arguments)`` if there is - a match (unless `return_rule` is True, in which case you get a tuple - in the form ``(rule, arguments)``) - - If the path info is not passed to the match method the default path - info of the map is used (defaults to the root URL if not defined - explicitly). - - All of the exceptions raised are subclasses of `HTTPException` so they - can be used as WSGI responses. They will all render generic error or - redirect pages. - - Here is a small example for matching: - - >>> m = Map([ - ... Rule('/', endpoint='index'), - ... Rule('/downloads/', endpoint='downloads/index'), - ... Rule('/downloads/', endpoint='downloads/show') - ... ]) - >>> urls = m.bind("example.com", "/") - >>> urls.match("/", "GET") - ('index', {}) - >>> urls.match("/downloads/42") - ('downloads/show', {'id': 42}) - - And here is what happens on redirect and missing URLs: - - >>> urls.match("/downloads") - Traceback (most recent call last): - ... - RequestRedirect: http://example.com/downloads/ - >>> urls.match("/missing") - Traceback (most recent call last): - ... - NotFound: 404 Not Found - - :param path_info: the path info to use for matching. Overrides the - path info specified on binding. - :param method: the HTTP method used for matching. Overrides the - method specified on binding. - :param return_rule: return the rule that matched instead of just the - endpoint (defaults to `False`). - :param query_args: optional query arguments that are used for - automatic redirects as string or dictionary. It's - currently not possible to use the query arguments - for URL matching. - :param websocket: Match WebSocket instead of HTTP requests. A - websocket request has a ``ws`` or ``wss`` - :attr:`url_scheme`. This overrides that detection. - - .. versionadded:: 1.0 - Added ``websocket``. - - .. versionchanged:: 0.8 - ``query_args`` can be a string. - - .. versionadded:: 0.7 - Added ``query_args``. - - .. versionadded:: 0.6 - Added ``return_rule``. - """ - self.map.update() - if path_info is None: - path_info = self.path_info - else: - path_info = to_unicode(path_info, self.map.charset) - if query_args is None: - query_args = self.query_args - method = (method or self.default_method).upper() - - if websocket is None: - websocket = self.websocket - - require_redirect = False - - path = u"%s|%s" % ( - self.map.host_matching and self.server_name or self.subdomain, - path_info and "/%s" % path_info.lstrip("/"), - ) - - have_match_for = set() - websocket_mismatch = False - - for rule in self.map._rules: - try: - rv = rule.match(path, method) - except RequestPath as e: - raise RequestRedirect( - self.make_redirect_url( - url_quote(e.path_info, self.map.charset, safe="/:|+"), - query_args, - ) - ) - except RequestAliasRedirect as e: - raise RequestRedirect( - self.make_alias_redirect_url( - path, rule.endpoint, e.matched_values, method, query_args - ) - ) - if rv is None: - continue - if rule.methods is not None and method not in rule.methods: - have_match_for.update(rule.methods) - continue - - if rule.websocket != websocket: - websocket_mismatch = True - continue - - if self.map.redirect_defaults: - redirect_url = self.get_default_redirect(rule, method, rv, query_args) - if redirect_url is not None: - raise RequestRedirect(redirect_url) - - if rule.redirect_to is not None: - if isinstance(rule.redirect_to, string_types): - - def _handle_match(match): - value = rv[match.group(1)] - return rule._converters[match.group(1)].to_url(value) - - redirect_url = _simple_rule_re.sub(_handle_match, rule.redirect_to) - else: - redirect_url = rule.redirect_to(self, **rv) - raise RequestRedirect( - str( - url_join( - "%s://%s%s%s" - % ( - self.url_scheme or "http", - self.subdomain + "." if self.subdomain else "", - self.server_name, - self.script_name, - ), - redirect_url, - ) - ) - ) - - if require_redirect: - raise RequestRedirect( - self.make_redirect_url( - url_quote(path_info, self.map.charset, safe="/:|+"), query_args - ) - ) - - if return_rule: - return rule, rv - else: - return rule.endpoint, rv - - if have_match_for: - raise MethodNotAllowed(valid_methods=list(have_match_for)) - - if websocket_mismatch: - raise WebsocketMismatch() - - raise NotFound() - - def test(self, path_info=None, method=None): - """Test if a rule would match. Works like `match` but returns `True` - if the URL matches, or `False` if it does not exist. - - :param path_info: the path info to use for matching. Overrides the - path info specified on binding. - :param method: the HTTP method used for matching. Overrides the - method specified on binding. - """ - try: - self.match(path_info, method) - except RequestRedirect: - pass - except HTTPException: - return False - return True - - def allowed_methods(self, path_info=None): - """Returns the valid methods that match for a given path. - - .. versionadded:: 0.7 - """ - try: - self.match(path_info, method="--") - except MethodNotAllowed as e: - return e.valid_methods - except HTTPException: - pass - return [] - - def get_host(self, domain_part): - """Figures out the full host name for the given domain part. The - domain part is a subdomain in case host matching is disabled or - a full host name. - """ - if self.map.host_matching: - if domain_part is None: - return self.server_name - return to_unicode(domain_part, "ascii") - subdomain = domain_part - if subdomain is None: - subdomain = self.subdomain - else: - subdomain = to_unicode(subdomain, "ascii") - return (subdomain + u"." if subdomain else u"") + self.server_name - - def get_default_redirect(self, rule, method, values, query_args): - """A helper that returns the URL to redirect to if it finds one. - This is used for default redirecting only. - - :internal: - """ - assert self.map.redirect_defaults - for r in self.map._rules_by_endpoint[rule.endpoint]: - # every rule that comes after this one, including ourself - # has a lower priority for the defaults. We order the ones - # with the highest priority up for building. - if r is rule: - break - if r.provides_defaults_for(rule) and r.suitable_for(values, method): - values.update(r.defaults) - domain_part, path = r.build(values) - return self.make_redirect_url(path, query_args, domain_part=domain_part) - - def encode_query_args(self, query_args): - if not isinstance(query_args, string_types): - query_args = url_encode(query_args, self.map.charset) - return query_args - - def make_redirect_url(self, path_info, query_args=None, domain_part=None): - """Creates a redirect URL. - - :internal: - """ - suffix = "" - if query_args: - suffix = "?" + self.encode_query_args(query_args) - return str( - "%s://%s/%s%s" - % ( - self.url_scheme or "http", - self.get_host(domain_part), - posixpath.join( - self.script_name[:-1].lstrip("/"), path_info.lstrip("/") - ), - suffix, - ) - ) - - def make_alias_redirect_url(self, path, endpoint, values, method, query_args): - """Internally called to make an alias redirect URL.""" - url = self.build( - endpoint, values, method, append_unknown=False, force_external=True - ) - if query_args: - url += "?" + self.encode_query_args(query_args) - assert url != path, "detected invalid alias setting. No canonical URL found" - return url - - def _partial_build(self, endpoint, values, method, append_unknown): - """Helper for :meth:`build`. Returns subdomain and path for the - rule that accepts this endpoint, values and method. - - :internal: - """ - # in case the method is none, try with the default method first - if method is None: - rv = self._partial_build( - endpoint, values, self.default_method, append_unknown - ) - if rv is not None: - return rv - - # Default method did not match or a specific method is passed. - # Check all for first match with matching host. If no matching - # host is found, go with first result. - first_match = None - - for rule in self.map._rules_by_endpoint.get(endpoint, ()): - if rule.suitable_for(values, method): - rv = rule.build(values, append_unknown) - - if rv is not None: - rv = (rv[0], rv[1], rule.websocket) - if self.map.host_matching: - if rv[0] == self.server_name: - return rv - elif first_match is None: - first_match = rv - else: - return rv - - return first_match - - def build( - self, - endpoint, - values=None, - method=None, - force_external=False, - append_unknown=True, - ): - """Building URLs works pretty much the other way round. Instead of - `match` you call `build` and pass it the endpoint and a dict of - arguments for the placeholders. - - The `build` function also accepts an argument called `force_external` - which, if you set it to `True` will force external URLs. Per default - external URLs (include the server name) will only be used if the - target URL is on a different subdomain. - - >>> m = Map([ - ... Rule('/', endpoint='index'), - ... Rule('/downloads/', endpoint='downloads/index'), - ... Rule('/downloads/', endpoint='downloads/show') - ... ]) - >>> urls = m.bind("example.com", "/") - >>> urls.build("index", {}) - '/' - >>> urls.build("downloads/show", {'id': 42}) - '/downloads/42' - >>> urls.build("downloads/show", {'id': 42}, force_external=True) - 'http://example.com/downloads/42' - - Because URLs cannot contain non ASCII data you will always get - bytestrings back. Non ASCII characters are urlencoded with the - charset defined on the map instance. - - Additional values are converted to unicode and appended to the URL as - URL querystring parameters: - - >>> urls.build("index", {'q': 'My Searchstring'}) - '/?q=My+Searchstring' - - When processing those additional values, lists are furthermore - interpreted as multiple values (as per - :py:class:`werkzeug.datastructures.MultiDict`): - - >>> urls.build("index", {'q': ['a', 'b', 'c']}) - '/?q=a&q=b&q=c' - - Passing a ``MultiDict`` will also add multiple values: - - >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 'b')))) - '/?p=z&q=a&q=b' - - If a rule does not exist when building a `BuildError` exception is - raised. - - The build method accepts an argument called `method` which allows you - to specify the method you want to have an URL built for if you have - different methods for the same endpoint specified. - - .. versionadded:: 0.6 - the `append_unknown` parameter was added. - - :param endpoint: the endpoint of the URL to build. - :param values: the values for the URL to build. Unhandled values are - appended to the URL as query parameters. - :param method: the HTTP method for the rule if there are different - URLs for different methods on the same endpoint. - :param force_external: enforce full canonical external URLs. If the URL - scheme is not provided, this will generate - a protocol-relative URL. - :param append_unknown: unknown parameters are appended to the generated - URL as query string argument. Disable this - if you want the builder to ignore those. - """ - self.map.update() - - if values: - if isinstance(values, MultiDict): - temp_values = {} - # iteritems(dict, values) is like `values.lists()` - # without the call or `list()` coercion overhead. - for key, value in iteritems(dict, values): - if not value: - continue - if len(value) == 1: # flatten single item lists - value = value[0] - if value is None: # drop None - continue - temp_values[key] = value - values = temp_values - else: - # drop None - values = dict(i for i in iteritems(values) if i[1] is not None) - else: - values = {} - - rv = self._partial_build(endpoint, values, method, append_unknown) - if rv is None: - raise BuildError(endpoint, values, method, self) - - domain_part, path, websocket = rv - host = self.get_host(domain_part) - - # Always build WebSocket routes with the scheme (browsers - # require full URLs). If bound to a WebSocket, ensure that HTTP - # routes are built with an HTTP scheme. - url_scheme = self.url_scheme - secure = url_scheme in {"https", "wss"} - - if websocket: - force_external = True - url_scheme = "wss" if secure else "ws" - elif url_scheme: - url_scheme = "https" if secure else "http" - - # shortcut this. - if not force_external and ( - (self.map.host_matching and host == self.server_name) - or (not self.map.host_matching and domain_part == self.subdomain) - ): - return "%s/%s" % (self.script_name.rstrip("/"), path.lstrip("/")) - return str( - "%s//%s%s/%s" - % ( - url_scheme + ":" if url_scheme else "", - host, - self.script_name[:-1], - path.lstrip("/"), - ) - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/security.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/security.py deleted file mode 100644 index 2308040..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/security.py +++ /dev/null @@ -1,249 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.security - ~~~~~~~~~~~~~~~~~ - - Security related helpers such as secure password hashing tools. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import hashlib -import hmac -import os -import posixpath -from random import SystemRandom -from struct import Struct - -from ._compat import izip -from ._compat import PY2 -from ._compat import range_type -from ._compat import text_type -from ._compat import to_bytes -from ._compat import to_native - -SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" -DEFAULT_PBKDF2_ITERATIONS = 150000 - -_pack_int = Struct(">I").pack -_builtin_safe_str_cmp = getattr(hmac, "compare_digest", None) -_sys_rng = SystemRandom() -_os_alt_seps = list( - sep for sep in [os.path.sep, os.path.altsep] if sep not in (None, "/") -) - - -def pbkdf2_hex( - data, salt, iterations=DEFAULT_PBKDF2_ITERATIONS, keylen=None, hashfunc=None -): - """Like :func:`pbkdf2_bin`, but returns a hex-encoded string. - - .. versionadded:: 0.9 - - :param data: the data to derive. - :param salt: the salt for the derivation. - :param iterations: the number of iterations. - :param keylen: the length of the resulting key. If not provided, - the digest size will be used. - :param hashfunc: the hash function to use. This can either be the - string name of a known hash function, or a function - from the hashlib module. Defaults to sha256. - """ - rv = pbkdf2_bin(data, salt, iterations, keylen, hashfunc) - return to_native(codecs.encode(rv, "hex_codec")) - - -def pbkdf2_bin( - data, salt, iterations=DEFAULT_PBKDF2_ITERATIONS, keylen=None, hashfunc=None -): - """Returns a binary digest for the PBKDF2 hash algorithm of `data` - with the given `salt`. It iterates `iterations` times and produces a - key of `keylen` bytes. By default, SHA-256 is used as hash function; - a different hashlib `hashfunc` can be provided. - - .. versionadded:: 0.9 - - :param data: the data to derive. - :param salt: the salt for the derivation. - :param iterations: the number of iterations. - :param keylen: the length of the resulting key. If not provided - the digest size will be used. - :param hashfunc: the hash function to use. This can either be the - string name of a known hash function or a function - from the hashlib module. Defaults to sha256. - """ - if not hashfunc: - hashfunc = "sha256" - - data = to_bytes(data) - salt = to_bytes(salt) - - if callable(hashfunc): - _test_hash = hashfunc() - hash_name = getattr(_test_hash, "name", None) - else: - hash_name = hashfunc - return hashlib.pbkdf2_hmac(hash_name, data, salt, iterations, keylen) - - -def safe_str_cmp(a, b): - """This function compares strings in somewhat constant time. This - requires that the length of at least one string is known in advance. - - Returns `True` if the two strings are equal, or `False` if they are not. - - .. versionadded:: 0.7 - """ - if isinstance(a, text_type): - a = a.encode("utf-8") - if isinstance(b, text_type): - b = b.encode("utf-8") - - if _builtin_safe_str_cmp is not None: - return _builtin_safe_str_cmp(a, b) - - if len(a) != len(b): - return False - - rv = 0 - if PY2: - for x, y in izip(a, b): - rv |= ord(x) ^ ord(y) - else: - for x, y in izip(a, b): - rv |= x ^ y - - return rv == 0 - - -def gen_salt(length): - """Generate a random string of SALT_CHARS with specified ``length``.""" - if length <= 0: - raise ValueError("Salt length must be positive") - return "".join(_sys_rng.choice(SALT_CHARS) for _ in range_type(length)) - - -def _hash_internal(method, salt, password): - """Internal password hash helper. Supports plaintext without salt, - unsalted and salted passwords. In case salted passwords are used - hmac is used. - """ - if method == "plain": - return password, method - - if isinstance(password, text_type): - password = password.encode("utf-8") - - if method.startswith("pbkdf2:"): - args = method[7:].split(":") - if len(args) not in (1, 2): - raise ValueError("Invalid number of arguments for PBKDF2") - method = args.pop(0) - iterations = args and int(args[0] or 0) or DEFAULT_PBKDF2_ITERATIONS - is_pbkdf2 = True - actual_method = "pbkdf2:%s:%d" % (method, iterations) - else: - is_pbkdf2 = False - actual_method = method - - if is_pbkdf2: - if not salt: - raise ValueError("Salt is required for PBKDF2") - rv = pbkdf2_hex(password, salt, iterations, hashfunc=method) - elif salt: - if isinstance(salt, text_type): - salt = salt.encode("utf-8") - mac = _create_mac(salt, password, method) - rv = mac.hexdigest() - else: - rv = hashlib.new(method, password).hexdigest() - return rv, actual_method - - -def _create_mac(key, msg, method): - if callable(method): - return hmac.HMAC(key, msg, method) - - def hashfunc(d=b""): - return hashlib.new(method, d) - - # Python 2.7 used ``hasattr(digestmod, '__call__')`` - # to detect if hashfunc is callable - hashfunc.__call__ = hashfunc - return hmac.HMAC(key, msg, hashfunc) - - -def generate_password_hash(password, method="pbkdf2:sha256", salt_length=8): - """Hash a password with the given method and salt with a string of - the given length. The format of the string returned includes the method - that was used so that :func:`check_password_hash` can check the hash. - - The format for the hashed string looks like this:: - - method$salt$hash - - This method can **not** generate unsalted passwords but it is possible - to set param method='plain' in order to enforce plaintext passwords. - If a salt is used, hmac is used internally to salt the password. - - If PBKDF2 is wanted it can be enabled by setting the method to - ``pbkdf2:method:iterations`` where iterations is optional:: - - pbkdf2:sha256:80000$salt$hash - pbkdf2:sha256$salt$hash - - :param password: the password to hash. - :param method: the hash method to use (one that hashlib supports). Can - optionally be in the format ``pbkdf2:[:iterations]`` - to enable PBKDF2. - :param salt_length: the length of the salt in letters. - """ - salt = gen_salt(salt_length) if method != "plain" else "" - h, actual_method = _hash_internal(method, salt, password) - return "%s$%s$%s" % (actual_method, salt, h) - - -def check_password_hash(pwhash, password): - """check a password against a given salted and hashed password value. - In order to support unsalted legacy passwords this method supports - plain text passwords, md5 and sha1 hashes (both salted and unsalted). - - Returns `True` if the password matched, `False` otherwise. - - :param pwhash: a hashed string like returned by - :func:`generate_password_hash`. - :param password: the plaintext password to compare against the hash. - """ - if pwhash.count("$") < 2: - return False - method, salt, hashval = pwhash.split("$", 2) - return safe_str_cmp(_hash_internal(method, salt, password)[0], hashval) - - -def safe_join(directory, *pathnames): - """Safely join zero or more untrusted path components to a base - directory to avoid escaping the base directory. - - :param directory: The trusted base directory. - :param pathnames: The untrusted path components relative to the - base directory. - :return: A safe path, otherwise ``None``. - """ - parts = [directory] - - for filename in pathnames: - if filename != "": - filename = posixpath.normpath(filename) - - if ( - any(sep in filename for sep in _os_alt_seps) - or os.path.isabs(filename) - or filename == ".." - or filename.startswith("../") - ): - return None - - parts.append(filename) - - return posixpath.join(*parts) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/serving.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/serving.py deleted file mode 100644 index f2a0dc9..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/serving.py +++ /dev/null @@ -1,1117 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.serving - ~~~~~~~~~~~~~~~~ - - There are many ways to serve a WSGI application. While you're developing - it you usually don't want a full blown webserver like Apache but a simple - standalone one. From Python 2.5 onwards there is the `wsgiref`_ server in - the standard library. If you're using older versions of Python you can - download the package from the cheeseshop. - - However there are some caveats. Sourcecode won't reload itself when - changed and each time you kill the server using ``^C`` you get an - `KeyboardInterrupt` error. While the latter is easy to solve the first - one can be a pain in the ass in some situations. - - The easiest way is creating a small ``start-myproject.py`` that runs the - application:: - - #!/usr/bin/env python - # -*- coding: utf-8 -*- - from myproject import make_app - from werkzeug.serving import run_simple - - app = make_app(...) - run_simple('localhost', 8080, app, use_reloader=True) - - You can also pass it a `extra_files` keyword argument with a list of - additional files (like configuration files) you want to observe. - - For bigger applications you should consider using `click` - (http://click.pocoo.org) instead of a simple start file. - - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import io -import os -import signal -import socket -import sys -from datetime import datetime as dt -from datetime import timedelta - -from ._compat import PY2 -from ._compat import reraise -from ._compat import WIN -from ._compat import wsgi_encoding_dance -from ._internal import _log -from .exceptions import InternalServerError -from .urls import uri_to_iri -from .urls import url_parse -from .urls import url_unquote - -try: - import socketserver - from http.server import BaseHTTPRequestHandler - from http.server import HTTPServer -except ImportError: - import SocketServer as socketserver - from BaseHTTPServer import HTTPServer - from BaseHTTPServer import BaseHTTPRequestHandler - -try: - import ssl -except ImportError: - - class _SslDummy(object): - def __getattr__(self, name): - raise RuntimeError("SSL support unavailable") - - ssl = _SslDummy() - -try: - import click -except ImportError: - click = None - - -ThreadingMixIn = socketserver.ThreadingMixIn -can_fork = hasattr(os, "fork") - -if can_fork: - ForkingMixIn = socketserver.ForkingMixIn -else: - - class ForkingMixIn(object): - pass - - -try: - af_unix = socket.AF_UNIX -except AttributeError: - af_unix = None - - -LISTEN_QUEUE = 128 -can_open_by_fd = not WIN and hasattr(socket, "fromfd") - -# On Python 3, ConnectionError represents the same errnos as -# socket.error from Python 2, while socket.error is an alias for the -# more generic OSError. -if PY2: - _ConnectionError = socket.error -else: - _ConnectionError = ConnectionError - - -class DechunkedInput(io.RawIOBase): - """An input stream that handles Transfer-Encoding 'chunked'""" - - def __init__(self, rfile): - self._rfile = rfile - self._done = False - self._len = 0 - - def readable(self): - return True - - def read_chunk_len(self): - try: - line = self._rfile.readline().decode("latin1") - _len = int(line.strip(), 16) - except ValueError: - raise IOError("Invalid chunk header") - if _len < 0: - raise IOError("Negative chunk length not allowed") - return _len - - def readinto(self, buf): - read = 0 - while not self._done and read < len(buf): - if self._len == 0: - # This is the first chunk or we fully consumed the previous - # one. Read the next length of the next chunk - self._len = self.read_chunk_len() - - if self._len == 0: - # Found the final chunk of size 0. The stream is now exhausted, - # but there is still a final newline that should be consumed - self._done = True - - if self._len > 0: - # There is data (left) in this chunk, so append it to the - # buffer. If this operation fully consumes the chunk, this will - # reset self._len to 0. - n = min(len(buf), self._len) - buf[read : read + n] = self._rfile.read(n) - self._len -= n - read += n - - if self._len == 0: - # Skip the terminating newline of a chunk that has been fully - # consumed. This also applies to the 0-sized final chunk - terminator = self._rfile.readline() - if terminator not in (b"\n", b"\r\n", b"\r"): - raise IOError("Missing chunk terminating newline") - - return read - - -class WSGIRequestHandler(BaseHTTPRequestHandler, object): - - """A request handler that implements WSGI dispatching.""" - - @property - def server_version(self): - from . import __version__ - - return "Werkzeug/" + __version__ - - def make_environ(self): - request_url = url_parse(self.path) - - def shutdown_server(): - self.server.shutdown_signal = True - - url_scheme = "http" if self.server.ssl_context is None else "https" - if not self.client_address: - self.client_address = "" - if isinstance(self.client_address, str): - self.client_address = (self.client_address, 0) - else: - pass - - # If there was no scheme but the path started with two slashes, - # the first segment may have been incorrectly parsed as the - # netloc, prepend it to the path again. - if not request_url.scheme and request_url.netloc: - path_info = "/%s%s" % (request_url.netloc, request_url.path) - else: - path_info = request_url.path - - path_info = url_unquote(path_info) - - environ = { - "wsgi.version": (1, 0), - "wsgi.url_scheme": url_scheme, - "wsgi.input": self.rfile, - "wsgi.errors": sys.stderr, - "wsgi.multithread": self.server.multithread, - "wsgi.multiprocess": self.server.multiprocess, - "wsgi.run_once": False, - "werkzeug.server.shutdown": shutdown_server, - "SERVER_SOFTWARE": self.server_version, - "REQUEST_METHOD": self.command, - "SCRIPT_NAME": "", - "PATH_INFO": wsgi_encoding_dance(path_info), - "QUERY_STRING": wsgi_encoding_dance(request_url.query), - # Non-standard, added by mod_wsgi, uWSGI - "REQUEST_URI": wsgi_encoding_dance(self.path), - # Non-standard, added by gunicorn - "RAW_URI": wsgi_encoding_dance(self.path), - "REMOTE_ADDR": self.address_string(), - "REMOTE_PORT": self.port_integer(), - "SERVER_NAME": self.server.server_address[0], - "SERVER_PORT": str(self.server.server_address[1]), - "SERVER_PROTOCOL": self.request_version, - } - - for key, value in self.get_header_items(): - key = key.upper().replace("-", "_") - value = value.replace("\r\n", "") - if key not in ("CONTENT_TYPE", "CONTENT_LENGTH"): - key = "HTTP_" + key - if key in environ: - value = "{},{}".format(environ[key], value) - environ[key] = value - - if environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked": - environ["wsgi.input_terminated"] = True - environ["wsgi.input"] = DechunkedInput(environ["wsgi.input"]) - - # Per RFC 2616, if the URL is absolute, use that as the host. - # We're using "has a scheme" to indicate an absolute URL. - if request_url.scheme and request_url.netloc: - environ["HTTP_HOST"] = request_url.netloc - - try: - # binary_form=False gives nicer information, but wouldn't be compatible with - # what Nginx or Apache could return. - peer_cert = self.connection.getpeercert(binary_form=True) - if peer_cert is not None: - # Nginx and Apache use PEM format. - environ["SSL_CLIENT_CERT"] = ssl.DER_cert_to_PEM_cert(peer_cert) - except ValueError: - # SSL handshake hasn't finished. - self.server.log("error", "Cannot fetch SSL peer certificate info") - except AttributeError: - # Not using TLS, the socket will not have getpeercert(). - pass - - return environ - - def run_wsgi(self): - if self.headers.get("Expect", "").lower().strip() == "100-continue": - self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") - - self.environ = environ = self.make_environ() - headers_set = [] - headers_sent = [] - - def write(data): - assert headers_set, "write() before start_response" - if not headers_sent: - status, response_headers = headers_sent[:] = headers_set - try: - code, msg = status.split(None, 1) - except ValueError: - code, msg = status, "" - code = int(code) - self.send_response(code, msg) - header_keys = set() - for key, value in response_headers: - self.send_header(key, value) - key = key.lower() - header_keys.add(key) - if not ( - "content-length" in header_keys - or environ["REQUEST_METHOD"] == "HEAD" - or code < 200 - or code in (204, 304) - ): - self.close_connection = True - self.send_header("Connection", "close") - if "server" not in header_keys: - self.send_header("Server", self.version_string()) - if "date" not in header_keys: - self.send_header("Date", self.date_time_string()) - self.end_headers() - - assert isinstance(data, bytes), "applications must write bytes" - if data: - # Only write data if there is any to avoid Python 3.5 SSL bug - self.wfile.write(data) - self.wfile.flush() - - def start_response(status, response_headers, exc_info=None): - if exc_info: - try: - if headers_sent: - reraise(*exc_info) - finally: - exc_info = None - elif headers_set: - raise AssertionError("Headers already set") - headers_set[:] = [status, response_headers] - return write - - def execute(app): - application_iter = app(environ, start_response) - try: - for data in application_iter: - write(data) - if not headers_sent: - write(b"") - finally: - if hasattr(application_iter, "close"): - application_iter.close() - - try: - execute(self.server.app) - except (_ConnectionError, socket.timeout) as e: - self.connection_dropped(e, environ) - except Exception: - if self.server.passthrough_errors: - raise - from .debug.tbtools import get_current_traceback - - traceback = get_current_traceback(ignore_system_exceptions=True) - try: - # if we haven't yet sent the headers but they are set - # we roll back to be able to set them again. - if not headers_sent: - del headers_set[:] - execute(InternalServerError()) - except Exception: - pass - self.server.log("error", "Error on request:\n%s", traceback.plaintext) - - def handle(self): - """Handles a request ignoring dropped connections.""" - try: - BaseHTTPRequestHandler.handle(self) - except (_ConnectionError, socket.timeout) as e: - self.connection_dropped(e) - except Exception as e: - if self.server.ssl_context is None or not is_ssl_error(e): - raise - if self.server.shutdown_signal: - self.initiate_shutdown() - - def initiate_shutdown(self): - """A horrible, horrible way to kill the server for Python 2.6 and - later. It's the best we can do. - """ - # Windows does not provide SIGKILL, go with SIGTERM then. - sig = getattr(signal, "SIGKILL", signal.SIGTERM) - # reloader active - if is_running_from_reloader(): - os.kill(os.getpid(), sig) - # python 2.7 - self.server._BaseServer__shutdown_request = True - # python 2.6 - self.server._BaseServer__serving = False - - def connection_dropped(self, error, environ=None): - """Called if the connection was closed by the client. By default - nothing happens. - """ - - def handle_one_request(self): - """Handle a single HTTP request.""" - self.raw_requestline = self.rfile.readline() - if not self.raw_requestline: - self.close_connection = 1 - elif self.parse_request(): - return self.run_wsgi() - - def send_response(self, code, message=None): - """Send the response header and log the response code.""" - self.log_request(code) - if message is None: - message = code in self.responses and self.responses[code][0] or "" - if self.request_version != "HTTP/0.9": - hdr = "%s %d %s\r\n" % (self.protocol_version, code, message) - self.wfile.write(hdr.encode("ascii")) - - def version_string(self): - return BaseHTTPRequestHandler.version_string(self).strip() - - def address_string(self): - if getattr(self, "environ", None): - return self.environ["REMOTE_ADDR"] - elif not self.client_address: - return "" - elif isinstance(self.client_address, str): - return self.client_address - else: - return self.client_address[0] - - def port_integer(self): - return self.client_address[1] - - def log_request(self, code="-", size="-"): - try: - path = uri_to_iri(self.path) - msg = "%s %s %s" % (self.command, path, self.request_version) - except AttributeError: - # path isn't set if the requestline was bad - msg = self.requestline - - code = str(code) - - if click: - color = click.style - - if code[0] == "1": # 1xx - Informational - msg = color(msg, bold=True) - elif code[0] == "2": # 2xx - Success - msg = color(msg, fg="white") - elif code == "304": # 304 - Resource Not Modified - msg = color(msg, fg="cyan") - elif code[0] == "3": # 3xx - Redirection - msg = color(msg, fg="green") - elif code == "404": # 404 - Resource Not Found - msg = color(msg, fg="yellow") - elif code[0] == "4": # 4xx - Client Error - msg = color(msg, fg="red", bold=True) - else: # 5xx, or any other response - msg = color(msg, fg="magenta", bold=True) - - self.log("info", '"%s" %s %s', msg, code, size) - - def log_error(self, *args): - self.log("error", *args) - - def log_message(self, format, *args): - self.log("info", format, *args) - - def log(self, type, message, *args): - _log( - type, - "%s - - [%s] %s\n" - % (self.address_string(), self.log_date_time_string(), message % args), - ) - - def get_header_items(self): - """ - Get an iterable list of key/value pairs representing headers. - - This function provides Python 2/3 compatibility as related to the - parsing of request headers. Python 2.7 is not compliant with - RFC 3875 Section 4.1.18 which requires multiple values for headers - to be provided or RFC 2616 which allows for folding of multi-line - headers. This function will return a matching list regardless - of Python version. It can be removed once Python 2.7 support - is dropped. - - :return: List of tuples containing header hey/value pairs - """ - if PY2: - # For Python 2, process the headers manually according to - # W3C RFC 2616 Section 4.2. - items = [] - for header in self.headers.headers: - # Remove "\r\n" from the header and split on ":" to get - # the field name and value. - try: - key, value = header[0:-2].split(":", 1) - except ValueError: - # If header could not be slit with : but starts with white - # space and it follows an existing header, it's a folded - # header. - if header[0] in ("\t", " ") and items: - # Pop off the last header - key, value = items.pop() - # Append the current header to the value of the last - # header which will be placed back on the end of the - # list - value = value + header - # Otherwise it's just a bad header and should error - else: - # Re-raise the value error - raise - - # Add the key and the value once stripped of leading - # white space. The specification allows for stripping - # trailing white space but the Python 3 code does not - # strip trailing white space. Therefore, trailing space - # will be left as is to match the Python 3 behavior. - items.append((key, value.lstrip())) - else: - items = self.headers.items() - - return items - - -#: backwards compatible name if someone is subclassing it -BaseRequestHandler = WSGIRequestHandler - - -def generate_adhoc_ssl_pair(cn=None): - try: - from cryptography import x509 - from cryptography.x509.oid import NameOID - from cryptography.hazmat.backends import default_backend - from cryptography.hazmat.primitives import hashes - from cryptography.hazmat.primitives.asymmetric import rsa - except ImportError: - raise TypeError("Using ad-hoc certificates requires the cryptography library.") - pkey = rsa.generate_private_key( - public_exponent=65537, key_size=2048, backend=default_backend() - ) - - # pretty damn sure that this is not actually accepted by anyone - if cn is None: - cn = u"*" - - subject = x509.Name( - [ - x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Dummy Certificate"), - x509.NameAttribute(NameOID.COMMON_NAME, cn), - ] - ) - - cert = ( - x509.CertificateBuilder() - .subject_name(subject) - .issuer_name(subject) - .public_key(pkey.public_key()) - .serial_number(x509.random_serial_number()) - .not_valid_before(dt.utcnow()) - .not_valid_after(dt.utcnow() + timedelta(days=365)) - .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False) - .add_extension( - x509.SubjectAlternativeName([x509.DNSName(u"*")]), critical=False - ) - .sign(pkey, hashes.SHA256(), default_backend()) - ) - return cert, pkey - - -def make_ssl_devcert(base_path, host=None, cn=None): - """Creates an SSL key for development. This should be used instead of - the ``'adhoc'`` key which generates a new cert on each server start. - It accepts a path for where it should store the key and cert and - either a host or CN. If a host is given it will use the CN - ``*.host/CN=host``. - - For more information see :func:`run_simple`. - - .. versionadded:: 0.9 - - :param base_path: the path to the certificate and key. The extension - ``.crt`` is added for the certificate, ``.key`` is - added for the key. - :param host: the name of the host. This can be used as an alternative - for the `cn`. - :param cn: the `CN` to use. - """ - - if host is not None: - cn = u"*.%s/CN=%s" % (host, host) - cert, pkey = generate_adhoc_ssl_pair(cn=cn) - - from cryptography.hazmat.primitives import serialization - - cert_file = base_path + ".crt" - pkey_file = base_path + ".key" - - with open(cert_file, "wb") as f: - f.write(cert.public_bytes(serialization.Encoding.PEM)) - with open(pkey_file, "wb") as f: - f.write( - pkey.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.TraditionalOpenSSL, - encryption_algorithm=serialization.NoEncryption(), - ) - ) - - return cert_file, pkey_file - - -def generate_adhoc_ssl_context(): - """Generates an adhoc SSL context for the development server.""" - import tempfile - import atexit - - cert, pkey = generate_adhoc_ssl_pair() - - from cryptography.hazmat.primitives import serialization - - cert_handle, cert_file = tempfile.mkstemp() - pkey_handle, pkey_file = tempfile.mkstemp() - atexit.register(os.remove, pkey_file) - atexit.register(os.remove, cert_file) - - os.write(cert_handle, cert.public_bytes(serialization.Encoding.PEM)) - os.write( - pkey_handle, - pkey.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.TraditionalOpenSSL, - encryption_algorithm=serialization.NoEncryption(), - ), - ) - - os.close(cert_handle) - os.close(pkey_handle) - ctx = load_ssl_context(cert_file, pkey_file) - return ctx - - -def load_ssl_context(cert_file, pkey_file=None, protocol=None): - """Loads SSL context from cert/private key files and optional protocol. - Many parameters are directly taken from the API of - :py:class:`ssl.SSLContext`. - - :param cert_file: Path of the certificate to use. - :param pkey_file: Path of the private key to use. If not given, the key - will be obtained from the certificate file. - :param protocol: One of the ``PROTOCOL_*`` constants in the stdlib ``ssl`` - module. Defaults to ``PROTOCOL_SSLv23``. - """ - if protocol is None: - try: - protocol = ssl.PROTOCOL_TLS_SERVER - except AttributeError: - # Python <= 3.5 compat - protocol = ssl.PROTOCOL_SSLv23 - ctx = _SSLContext(protocol) - ctx.load_cert_chain(cert_file, pkey_file) - return ctx - - -class _SSLContext(object): - - """A dummy class with a small subset of Python3's ``ssl.SSLContext``, only - intended to be used with and by Werkzeug.""" - - def __init__(self, protocol): - self._protocol = protocol - self._certfile = None - self._keyfile = None - self._password = None - - def load_cert_chain(self, certfile, keyfile=None, password=None): - self._certfile = certfile - self._keyfile = keyfile or certfile - self._password = password - - def wrap_socket(self, sock, **kwargs): - return ssl.wrap_socket( - sock, - keyfile=self._keyfile, - certfile=self._certfile, - ssl_version=self._protocol, - **kwargs - ) - - -def is_ssl_error(error=None): - """Checks if the given error (or the current one) is an SSL error.""" - if error is None: - error = sys.exc_info()[1] - return isinstance(error, ssl.SSLError) - - -def select_address_family(host, port): - """Return ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending on - the host and port.""" - # disabled due to problems with current ipv6 implementations - # and various operating systems. Probably this code also is - # not supposed to work, but I can't come up with any other - # ways to implement this. - # try: - # info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, - # socket.SOCK_STREAM, 0, - # socket.AI_PASSIVE) - # if info: - # return info[0][0] - # except socket.gaierror: - # pass - if host.startswith("unix://"): - return socket.AF_UNIX - elif ":" in host and hasattr(socket, "AF_INET6"): - return socket.AF_INET6 - return socket.AF_INET - - -def get_sockaddr(host, port, family): - """Return a fully qualified socket address that can be passed to - :func:`socket.bind`.""" - if family == af_unix: - return host.split("://", 1)[1] - try: - res = socket.getaddrinfo( - host, port, family, socket.SOCK_STREAM, socket.IPPROTO_TCP - ) - except socket.gaierror: - return host, port - return res[0][4] - - -class BaseWSGIServer(HTTPServer, object): - - """Simple single-threaded, single-process WSGI server.""" - - multithread = False - multiprocess = False - request_queue_size = LISTEN_QUEUE - - def __init__( - self, - host, - port, - app, - handler=None, - passthrough_errors=False, - ssl_context=None, - fd=None, - ): - if handler is None: - handler = WSGIRequestHandler - - self.address_family = select_address_family(host, port) - - if fd is not None: - real_sock = socket.fromfd(fd, self.address_family, socket.SOCK_STREAM) - port = 0 - - server_address = get_sockaddr(host, int(port), self.address_family) - - # remove socket file if it already exists - if self.address_family == af_unix and os.path.exists(server_address): - os.unlink(server_address) - HTTPServer.__init__(self, server_address, handler) - - self.app = app - self.passthrough_errors = passthrough_errors - self.shutdown_signal = False - self.host = host - self.port = self.socket.getsockname()[1] - - # Patch in the original socket. - if fd is not None: - self.socket.close() - self.socket = real_sock - self.server_address = self.socket.getsockname() - - if ssl_context is not None: - if isinstance(ssl_context, tuple): - ssl_context = load_ssl_context(*ssl_context) - if ssl_context == "adhoc": - ssl_context = generate_adhoc_ssl_context() - - # If we are on Python 2 the return value from socket.fromfd - # is an internal socket object but what we need for ssl wrap - # is the wrapper around it :( - sock = self.socket - if PY2 and not isinstance(sock, socket.socket): - sock = socket.socket(sock.family, sock.type, sock.proto, sock) - self.socket = ssl_context.wrap_socket(sock, server_side=True) - self.ssl_context = ssl_context - else: - self.ssl_context = None - - def log(self, type, message, *args): - _log(type, message, *args) - - def serve_forever(self): - self.shutdown_signal = False - try: - HTTPServer.serve_forever(self) - except KeyboardInterrupt: - pass - finally: - self.server_close() - - def handle_error(self, request, client_address): - if self.passthrough_errors: - raise - # Python 2 still causes a socket.error after the earlier - # handling, so silence it here. - if isinstance(sys.exc_info()[1], _ConnectionError): - return - return HTTPServer.handle_error(self, request, client_address) - - def get_request(self): - con, info = self.socket.accept() - return con, info - - -class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer): - - """A WSGI server that does threading.""" - - multithread = True - daemon_threads = True - - -class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): - - """A WSGI server that does forking.""" - - multiprocess = True - - def __init__( - self, - host, - port, - app, - processes=40, - handler=None, - passthrough_errors=False, - ssl_context=None, - fd=None, - ): - if not can_fork: - raise ValueError("Your platform does not support forking.") - BaseWSGIServer.__init__( - self, host, port, app, handler, passthrough_errors, ssl_context, fd - ) - self.max_children = processes - - -def make_server( - host=None, - port=None, - app=None, - threaded=False, - processes=1, - request_handler=None, - passthrough_errors=False, - ssl_context=None, - fd=None, -): - """Create a new server instance that is either threaded, or forks - or just processes one request after another. - """ - if threaded and processes > 1: - raise ValueError("cannot have a multithreaded and multi process server.") - elif threaded: - return ThreadedWSGIServer( - host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd - ) - elif processes > 1: - return ForkingWSGIServer( - host, - port, - app, - processes, - request_handler, - passthrough_errors, - ssl_context, - fd=fd, - ) - else: - return BaseWSGIServer( - host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd - ) - - -def is_running_from_reloader(): - """Checks if the application is running from within the Werkzeug - reloader subprocess. - - .. versionadded:: 0.10 - """ - return os.environ.get("WERKZEUG_RUN_MAIN") == "true" - - -def run_simple( - hostname, - port, - application, - use_reloader=False, - use_debugger=False, - use_evalex=True, - extra_files=None, - reloader_interval=1, - reloader_type="auto", - threaded=False, - processes=1, - request_handler=None, - static_files=None, - passthrough_errors=False, - ssl_context=None, -): - """Start a WSGI application. Optional features include a reloader, - multithreading and fork support. - - This function has a command-line interface too:: - - python -m werkzeug.serving --help - - .. versionadded:: 0.5 - `static_files` was added to simplify serving of static files as well - as `passthrough_errors`. - - .. versionadded:: 0.6 - support for SSL was added. - - .. versionadded:: 0.8 - Added support for automatically loading a SSL context from certificate - file and private key. - - .. versionadded:: 0.9 - Added command-line interface. - - .. versionadded:: 0.10 - Improved the reloader and added support for changing the backend - through the `reloader_type` parameter. See :ref:`reloader` - for more information. - - .. versionchanged:: 0.15 - Bind to a Unix socket by passing a path that starts with - ``unix://`` as the ``hostname``. - - :param hostname: The host to bind to, for example ``'localhost'``. - If the value is a path that starts with ``unix://`` it will bind - to a Unix socket instead of a TCP socket.. - :param port: The port for the server. eg: ``8080`` - :param application: the WSGI application to execute - :param use_reloader: should the server automatically restart the python - process if modules were changed? - :param use_debugger: should the werkzeug debugging system be used? - :param use_evalex: should the exception evaluation feature be enabled? - :param extra_files: a list of files the reloader should watch - additionally to the modules. For example configuration - files. - :param reloader_interval: the interval for the reloader in seconds. - :param reloader_type: the type of reloader to use. The default is - auto detection. Valid values are ``'stat'`` and - ``'watchdog'``. See :ref:`reloader` for more - information. - :param threaded: should the process handle each request in a separate - thread? - :param processes: if greater than 1 then handle each request in a new process - up to this maximum number of concurrent processes. - :param request_handler: optional parameter that can be used to replace - the default one. You can use this to replace it - with a different - :class:`~BaseHTTPServer.BaseHTTPRequestHandler` - subclass. - :param static_files: a list or dict of paths for static files. This works - exactly like :class:`SharedDataMiddleware`, it's actually - just wrapping the application in that middleware before - serving. - :param passthrough_errors: set this to `True` to disable the error catching. - This means that the server will die on errors but - it can be useful to hook debuggers in (pdb etc.) - :param ssl_context: an SSL context for the connection. Either an - :class:`ssl.SSLContext`, a tuple in the form - ``(cert_file, pkey_file)``, the string ``'adhoc'`` if - the server should automatically create one, or ``None`` - to disable SSL (which is the default). - """ - if not isinstance(port, int): - raise TypeError("port must be an integer") - if use_debugger: - from .debug import DebuggedApplication - - application = DebuggedApplication(application, use_evalex) - if static_files: - from .middleware.shared_data import SharedDataMiddleware - - application = SharedDataMiddleware(application, static_files) - - def log_startup(sock): - display_hostname = hostname if hostname not in ("", "*") else "localhost" - quit_msg = "(Press CTRL+C to quit)" - if sock.family == af_unix: - _log("info", " * Running on %s %s", display_hostname, quit_msg) - else: - if ":" in display_hostname: - display_hostname = "[%s]" % display_hostname - port = sock.getsockname()[1] - _log( - "info", - " * Running on %s://%s:%d/ %s", - "http" if ssl_context is None else "https", - display_hostname, - port, - quit_msg, - ) - - def inner(): - try: - fd = int(os.environ["WERKZEUG_SERVER_FD"]) - except (LookupError, ValueError): - fd = None - srv = make_server( - hostname, - port, - application, - threaded, - processes, - request_handler, - passthrough_errors, - ssl_context, - fd=fd, - ) - if fd is None: - log_startup(srv.socket) - srv.serve_forever() - - if use_reloader: - # If we're not running already in the subprocess that is the - # reloader we want to open up a socket early to make sure the - # port is actually available. - if not is_running_from_reloader(): - if port == 0 and not can_open_by_fd: - raise ValueError( - "Cannot bind to a random port with enabled " - "reloader if the Python interpreter does " - "not support socket opening by fd." - ) - - # Create and destroy a socket so that any exceptions are - # raised before we spawn a separate Python interpreter and - # lose this ability. - address_family = select_address_family(hostname, port) - server_address = get_sockaddr(hostname, port, address_family) - s = socket.socket(address_family, socket.SOCK_STREAM) - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.bind(server_address) - if hasattr(s, "set_inheritable"): - s.set_inheritable(True) - - # If we can open the socket by file descriptor, then we can just - # reuse this one and our socket will survive the restarts. - if can_open_by_fd: - os.environ["WERKZEUG_SERVER_FD"] = str(s.fileno()) - s.listen(LISTEN_QUEUE) - log_startup(s) - else: - s.close() - if address_family == af_unix: - _log("info", "Unlinking %s" % server_address) - os.unlink(server_address) - - # Do not use relative imports, otherwise "python -m werkzeug.serving" - # breaks. - from ._reloader import run_with_reloader - - run_with_reloader(inner, extra_files, reloader_interval, reloader_type) - else: - inner() - - -def run_with_reloader(*args, **kwargs): - # People keep using undocumented APIs. Do not use this function - # please, we do not guarantee that it continues working. - from ._reloader import run_with_reloader - - return run_with_reloader(*args, **kwargs) - - -def main(): - """A simple command-line interface for :py:func:`run_simple`.""" - - # in contrast to argparse, this works at least under Python < 2.7 - import optparse - from .utils import import_string - - parser = optparse.OptionParser(usage="Usage: %prog [options] app_module:app_object") - parser.add_option( - "-b", - "--bind", - dest="address", - help="The hostname:port the app should listen on.", - ) - parser.add_option( - "-d", - "--debug", - dest="use_debugger", - action="store_true", - default=False, - help="Use Werkzeug's debugger.", - ) - parser.add_option( - "-r", - "--reload", - dest="use_reloader", - action="store_true", - default=False, - help="Reload Python process if modules change.", - ) - options, args = parser.parse_args() - - hostname, port = None, None - if options.address: - address = options.address.split(":") - hostname = address[0] - if len(address) > 1: - port = address[1] - - if len(args) != 1: - sys.stdout.write("No application supplied, or too much. See --help\n") - sys.exit(1) - app = import_string(args[0]) - - run_simple( - hostname=(hostname or "127.0.0.1"), - port=int(port or 5000), - application=app, - use_reloader=options.use_reloader, - use_debugger=options.use_debugger, - ) - - -if __name__ == "__main__": - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/test.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/test.py deleted file mode 100644 index c5ce50a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/test.py +++ /dev/null @@ -1,1123 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.test - ~~~~~~~~~~~~~ - - This module implements a client to WSGI applications for testing. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import mimetypes -import sys -from io import BytesIO -from itertools import chain -from random import random -from tempfile import TemporaryFile -from time import time - -from ._compat import iteritems -from ._compat import iterlists -from ._compat import itervalues -from ._compat import make_literal_wrapper -from ._compat import reraise -from ._compat import string_types -from ._compat import text_type -from ._compat import to_bytes -from ._compat import wsgi_encoding_dance -from ._internal import _get_environ -from .datastructures import CallbackDict -from .datastructures import CombinedMultiDict -from .datastructures import EnvironHeaders -from .datastructures import FileMultiDict -from .datastructures import Headers -from .datastructures import MultiDict -from .http import dump_cookie -from .http import dump_options_header -from .http import parse_options_header -from .urls import iri_to_uri -from .urls import url_encode -from .urls import url_fix -from .urls import url_parse -from .urls import url_unparse -from .urls import url_unquote -from .utils import get_content_type -from .wrappers import BaseRequest -from .wsgi import ClosingIterator -from .wsgi import get_current_url - -try: - from urllib.request import Request as U2Request -except ImportError: - from urllib2 import Request as U2Request - -try: - from http.cookiejar import CookieJar -except ImportError: - from cookielib import CookieJar - - -def stream_encode_multipart( - values, use_tempfile=True, threshold=1024 * 500, boundary=None, charset="utf-8" -): - """Encode a dict of values (either strings or file descriptors or - :class:`FileStorage` objects.) into a multipart encoded string stored - in a file descriptor. - """ - if boundary is None: - boundary = "---------------WerkzeugFormPart_%s%s" % (time(), random()) - _closure = [BytesIO(), 0, False] - - if use_tempfile: - - def write_binary(string): - stream, total_length, on_disk = _closure - if on_disk: - stream.write(string) - else: - length = len(string) - if length + _closure[1] <= threshold: - stream.write(string) - else: - new_stream = TemporaryFile("wb+") - new_stream.write(stream.getvalue()) - new_stream.write(string) - _closure[0] = new_stream - _closure[2] = True - _closure[1] = total_length + length - - else: - write_binary = _closure[0].write - - def write(string): - write_binary(string.encode(charset)) - - if not isinstance(values, MultiDict): - values = MultiDict(values) - - for key, values in iterlists(values): - for value in values: - write('--%s\r\nContent-Disposition: form-data; name="%s"' % (boundary, key)) - reader = getattr(value, "read", None) - if reader is not None: - filename = getattr(value, "filename", getattr(value, "name", None)) - content_type = getattr(value, "content_type", None) - if content_type is None: - content_type = ( - filename - and mimetypes.guess_type(filename)[0] - or "application/octet-stream" - ) - if filename is not None: - write('; filename="%s"\r\n' % filename) - else: - write("\r\n") - write("Content-Type: %s\r\n\r\n" % content_type) - while 1: - chunk = reader(16384) - if not chunk: - break - write_binary(chunk) - else: - if not isinstance(value, string_types): - value = str(value) - - value = to_bytes(value, charset) - write("\r\n\r\n") - write_binary(value) - write("\r\n") - write("--%s--\r\n" % boundary) - - length = int(_closure[0].tell()) - _closure[0].seek(0) - return _closure[0], length, boundary - - -def encode_multipart(values, boundary=None, charset="utf-8"): - """Like `stream_encode_multipart` but returns a tuple in the form - (``boundary``, ``data``) where data is a bytestring. - """ - stream, length, boundary = stream_encode_multipart( - values, use_tempfile=False, boundary=boundary, charset=charset - ) - return boundary, stream.read() - - -class _TestCookieHeaders(object): - - """A headers adapter for cookielib - """ - - def __init__(self, headers): - self.headers = headers - - def getheaders(self, name): - headers = [] - name = name.lower() - for k, v in self.headers: - if k.lower() == name: - headers.append(v) - return headers - - def get_all(self, name, default=None): - rv = [] - for k, v in self.headers: - if k.lower() == name.lower(): - rv.append(v) - return rv or default or [] - - -class _TestCookieResponse(object): - - """Something that looks like a httplib.HTTPResponse, but is actually just an - adapter for our test responses to make them available for cookielib. - """ - - def __init__(self, headers): - self.headers = _TestCookieHeaders(headers) - - def info(self): - return self.headers - - -class _TestCookieJar(CookieJar): - - """A cookielib.CookieJar modified to inject and read cookie headers from - and to wsgi environments, and wsgi application responses. - """ - - def inject_wsgi(self, environ): - """Inject the cookies as client headers into the server's wsgi - environment. - """ - cvals = ["%s=%s" % (c.name, c.value) for c in self] - - if cvals: - environ["HTTP_COOKIE"] = "; ".join(cvals) - else: - environ.pop("HTTP_COOKIE", None) - - def extract_wsgi(self, environ, headers): - """Extract the server's set-cookie headers as cookies into the - cookie jar. - """ - self.extract_cookies( - _TestCookieResponse(headers), U2Request(get_current_url(environ)) - ) - - -def _iter_data(data): - """Iterates over a `dict` or :class:`MultiDict` yielding all keys and - values. - This is used to iterate over the data passed to the - :class:`EnvironBuilder`. - """ - if isinstance(data, MultiDict): - for key, values in iterlists(data): - for value in values: - yield key, value - else: - for key, values in iteritems(data): - if isinstance(values, list): - for value in values: - yield key, value - else: - yield key, values - - -class EnvironBuilder(object): - """This class can be used to conveniently create a WSGI environment - for testing purposes. It can be used to quickly create WSGI environments - or request objects from arbitrary data. - - The signature of this class is also used in some other places as of - Werkzeug 0.5 (:func:`create_environ`, :meth:`BaseResponse.from_values`, - :meth:`Client.open`). Because of this most of the functionality is - available through the constructor alone. - - Files and regular form data can be manipulated independently of each - other with the :attr:`form` and :attr:`files` attributes, but are - passed with the same argument to the constructor: `data`. - - `data` can be any of these values: - - - a `str` or `bytes` object: The object is converted into an - :attr:`input_stream`, the :attr:`content_length` is set and you have to - provide a :attr:`content_type`. - - a `dict` or :class:`MultiDict`: The keys have to be strings. The values - have to be either any of the following objects, or a list of any of the - following objects: - - - a :class:`file`-like object: These are converted into - :class:`FileStorage` objects automatically. - - a `tuple`: The :meth:`~FileMultiDict.add_file` method is called - with the key and the unpacked `tuple` items as positional - arguments. - - a `str`: The string is set as form data for the associated key. - - a file-like object: The object content is loaded in memory and then - handled like a regular `str` or a `bytes`. - - :param path: the path of the request. In the WSGI environment this will - end up as `PATH_INFO`. If the `query_string` is not defined - and there is a question mark in the `path` everything after - it is used as query string. - :param base_url: the base URL is a URL that is used to extract the WSGI - URL scheme, host (server name + server port) and the - script root (`SCRIPT_NAME`). - :param query_string: an optional string or dict with URL parameters. - :param method: the HTTP method to use, defaults to `GET`. - :param input_stream: an optional input stream. Do not specify this and - `data`. As soon as an input stream is set you can't - modify :attr:`args` and :attr:`files` unless you - set the :attr:`input_stream` to `None` again. - :param content_type: The content type for the request. As of 0.5 you - don't have to provide this when specifying files - and form data via `data`. - :param content_length: The content length for the request. You don't - have to specify this when providing data via - `data`. - :param errors_stream: an optional error stream that is used for - `wsgi.errors`. Defaults to :data:`stderr`. - :param multithread: controls `wsgi.multithread`. Defaults to `False`. - :param multiprocess: controls `wsgi.multiprocess`. Defaults to `False`. - :param run_once: controls `wsgi.run_once`. Defaults to `False`. - :param headers: an optional list or :class:`Headers` object of headers. - :param data: a string or dict of form data or a file-object. - See explanation above. - :param json: An object to be serialized and assigned to ``data``. - Defaults the content type to ``"application/json"``. - Serialized with the function assigned to :attr:`json_dumps`. - :param environ_base: an optional dict of environment defaults. - :param environ_overrides: an optional dict of environment overrides. - :param charset: the charset used to encode unicode data. - - .. versionadded:: 0.15 - The ``json`` param and :meth:`json_dumps` method. - - .. versionadded:: 0.15 - The environ has keys ``REQUEST_URI`` and ``RAW_URI`` containing - the path before perecent-decoding. This is not part of the WSGI - PEP, but many WSGI servers include it. - - .. versionchanged:: 0.6 - ``path`` and ``base_url`` can now be unicode strings that are - encoded with :func:`iri_to_uri`. - """ - - #: the server protocol to use. defaults to HTTP/1.1 - server_protocol = "HTTP/1.1" - - #: the wsgi version to use. defaults to (1, 0) - wsgi_version = (1, 0) - - #: the default request class for :meth:`get_request` - request_class = BaseRequest - - import json - - #: The serialization function used when ``json`` is passed. - json_dumps = staticmethod(json.dumps) - del json - - def __init__( - self, - path="/", - base_url=None, - query_string=None, - method="GET", - input_stream=None, - content_type=None, - content_length=None, - errors_stream=None, - multithread=False, - multiprocess=False, - run_once=False, - headers=None, - data=None, - environ_base=None, - environ_overrides=None, - charset="utf-8", - mimetype=None, - json=None, - ): - path_s = make_literal_wrapper(path) - if query_string is not None and path_s("?") in path: - raise ValueError("Query string is defined in the path and as an argument") - if query_string is None and path_s("?") in path: - path, query_string = path.split(path_s("?"), 1) - self.charset = charset - self.path = iri_to_uri(path) - if base_url is not None: - base_url = url_fix(iri_to_uri(base_url, charset), charset) - self.base_url = base_url - if isinstance(query_string, (bytes, text_type)): - self.query_string = query_string - else: - if query_string is None: - query_string = MultiDict() - elif not isinstance(query_string, MultiDict): - query_string = MultiDict(query_string) - self.args = query_string - self.method = method - if headers is None: - headers = Headers() - elif not isinstance(headers, Headers): - headers = Headers(headers) - self.headers = headers - if content_type is not None: - self.content_type = content_type - if errors_stream is None: - errors_stream = sys.stderr - self.errors_stream = errors_stream - self.multithread = multithread - self.multiprocess = multiprocess - self.run_once = run_once - self.environ_base = environ_base - self.environ_overrides = environ_overrides - self.input_stream = input_stream - self.content_length = content_length - self.closed = False - - if json is not None: - if data is not None: - raise TypeError("can't provide both json and data") - - data = self.json_dumps(json) - - if self.content_type is None: - self.content_type = "application/json" - - if data: - if input_stream is not None: - raise TypeError("can't provide input stream and data") - if hasattr(data, "read"): - data = data.read() - if isinstance(data, text_type): - data = data.encode(self.charset) - if isinstance(data, bytes): - self.input_stream = BytesIO(data) - if self.content_length is None: - self.content_length = len(data) - else: - for key, value in _iter_data(data): - if isinstance(value, (tuple, dict)) or hasattr(value, "read"): - self._add_file_from_data(key, value) - else: - self.form.setlistdefault(key).append(value) - - if mimetype is not None: - self.mimetype = mimetype - - @classmethod - def from_environ(cls, environ, **kwargs): - """Turn an environ dict back into a builder. Any extra kwargs - override the args extracted from the environ. - - .. versionadded:: 0.15 - """ - headers = Headers(EnvironHeaders(environ)) - out = { - "path": environ["PATH_INFO"], - "base_url": cls._make_base_url( - environ["wsgi.url_scheme"], headers.pop("Host"), environ["SCRIPT_NAME"] - ), - "query_string": environ["QUERY_STRING"], - "method": environ["REQUEST_METHOD"], - "input_stream": environ["wsgi.input"], - "content_type": headers.pop("Content-Type", None), - "content_length": headers.pop("Content-Length", None), - "errors_stream": environ["wsgi.errors"], - "multithread": environ["wsgi.multithread"], - "multiprocess": environ["wsgi.multiprocess"], - "run_once": environ["wsgi.run_once"], - "headers": headers, - } - out.update(kwargs) - return cls(**out) - - def _add_file_from_data(self, key, value): - """Called in the EnvironBuilder to add files from the data dict.""" - if isinstance(value, tuple): - self.files.add_file(key, *value) - else: - self.files.add_file(key, value) - - @staticmethod - def _make_base_url(scheme, host, script_root): - return url_unparse((scheme, host, script_root, "", "")).rstrip("/") + "/" - - @property - def base_url(self): - """The base URL is used to extract the URL scheme, host name, - port, and root path. - """ - return self._make_base_url(self.url_scheme, self.host, self.script_root) - - @base_url.setter - def base_url(self, value): - if value is None: - scheme = "http" - netloc = "localhost" - script_root = "" - else: - scheme, netloc, script_root, qs, anchor = url_parse(value) - if qs or anchor: - raise ValueError("base url must not contain a query string or fragment") - self.script_root = script_root.rstrip("/") - self.host = netloc - self.url_scheme = scheme - - @property - def content_type(self): - """The content type for the request. Reflected from and to - the :attr:`headers`. Do not set if you set :attr:`files` or - :attr:`form` for auto detection. - """ - ct = self.headers.get("Content-Type") - if ct is None and not self._input_stream: - if self._files: - return "multipart/form-data" - if self._form: - return "application/x-www-form-urlencoded" - return None - return ct - - @content_type.setter - def content_type(self, value): - if value is None: - self.headers.pop("Content-Type", None) - else: - self.headers["Content-Type"] = value - - @property - def mimetype(self): - """The mimetype (content type without charset etc.) - - .. versionadded:: 0.14 - """ - ct = self.content_type - return ct.split(";")[0].strip() if ct else None - - @mimetype.setter - def mimetype(self, value): - self.content_type = get_content_type(value, self.charset) - - @property - def mimetype_params(self): - """ The mimetype parameters as dict. For example if the - content type is ``text/html; charset=utf-8`` the params would be - ``{'charset': 'utf-8'}``. - - .. versionadded:: 0.14 - """ - - def on_update(d): - self.headers["Content-Type"] = dump_options_header(self.mimetype, d) - - d = parse_options_header(self.headers.get("content-type", ""))[1] - return CallbackDict(d, on_update) - - @property - def content_length(self): - """The content length as integer. Reflected from and to the - :attr:`headers`. Do not set if you set :attr:`files` or - :attr:`form` for auto detection. - """ - return self.headers.get("Content-Length", type=int) - - @content_length.setter - def content_length(self, value): - if value is None: - self.headers.pop("Content-Length", None) - else: - self.headers["Content-Length"] = str(value) - - def _get_form(self, name, storage): - """Common behavior for getting the :attr:`form` and - :attr:`files` properties. - - :param name: Name of the internal cached attribute. - :param storage: Storage class used for the data. - """ - if self.input_stream is not None: - raise AttributeError("an input stream is defined") - - rv = getattr(self, name) - - if rv is None: - rv = storage() - setattr(self, name, rv) - - return rv - - def _set_form(self, name, value): - """Common behavior for setting the :attr:`form` and - :attr:`files` properties. - - :param name: Name of the internal cached attribute. - :param value: Value to assign to the attribute. - """ - self._input_stream = None - setattr(self, name, value) - - @property - def form(self): - """A :class:`MultiDict` of form values.""" - return self._get_form("_form", MultiDict) - - @form.setter - def form(self, value): - self._set_form("_form", value) - - @property - def files(self): - """A :class:`FileMultiDict` of uploaded files. Use - :meth:`~FileMultiDict.add_file` to add new files. - """ - return self._get_form("_files", FileMultiDict) - - @files.setter - def files(self, value): - self._set_form("_files", value) - - @property - def input_stream(self): - """An optional input stream. If you set this it will clear - :attr:`form` and :attr:`files`. - """ - return self._input_stream - - @input_stream.setter - def input_stream(self, value): - self._input_stream = value - self._form = None - self._files = None - - @property - def query_string(self): - """The query string. If you set this to a string - :attr:`args` will no longer be available. - """ - if self._query_string is None: - if self._args is not None: - return url_encode(self._args, charset=self.charset) - return "" - return self._query_string - - @query_string.setter - def query_string(self, value): - self._query_string = value - self._args = None - - @property - def args(self): - """The URL arguments as :class:`MultiDict`.""" - if self._query_string is not None: - raise AttributeError("a query string is defined") - if self._args is None: - self._args = MultiDict() - return self._args - - @args.setter - def args(self, value): - self._query_string = None - self._args = value - - @property - def server_name(self): - """The server name (read-only, use :attr:`host` to set)""" - return self.host.split(":", 1)[0] - - @property - def server_port(self): - """The server port as integer (read-only, use :attr:`host` to set)""" - pieces = self.host.split(":", 1) - if len(pieces) == 2 and pieces[1].isdigit(): - return int(pieces[1]) - if self.url_scheme == "https": - return 443 - return 80 - - def __del__(self): - try: - self.close() - except Exception: - pass - - def close(self): - """Closes all files. If you put real :class:`file` objects into the - :attr:`files` dict you can call this method to automatically close - them all in one go. - """ - if self.closed: - return - try: - files = itervalues(self.files) - except AttributeError: - files = () - for f in files: - try: - f.close() - except Exception: - pass - self.closed = True - - def get_environ(self): - """Return the built environ. - - .. versionchanged:: 0.15 - The content type and length headers are set based on - input stream detection. Previously this only set the WSGI - keys. - """ - input_stream = self.input_stream - content_length = self.content_length - - mimetype = self.mimetype - content_type = self.content_type - - if input_stream is not None: - start_pos = input_stream.tell() - input_stream.seek(0, 2) - end_pos = input_stream.tell() - input_stream.seek(start_pos) - content_length = end_pos - start_pos - elif mimetype == "multipart/form-data": - values = CombinedMultiDict([self.form, self.files]) - input_stream, content_length, boundary = stream_encode_multipart( - values, charset=self.charset - ) - content_type = mimetype + '; boundary="%s"' % boundary - elif mimetype == "application/x-www-form-urlencoded": - # XXX: py2v3 review - values = url_encode(self.form, charset=self.charset) - values = values.encode("ascii") - content_length = len(values) - input_stream = BytesIO(values) - else: - input_stream = BytesIO() - - result = {} - if self.environ_base: - result.update(self.environ_base) - - def _path_encode(x): - return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset) - - qs = wsgi_encoding_dance(self.query_string) - - result.update( - { - "REQUEST_METHOD": self.method, - "SCRIPT_NAME": _path_encode(self.script_root), - "PATH_INFO": _path_encode(self.path), - "QUERY_STRING": qs, - # Non-standard, added by mod_wsgi, uWSGI - "REQUEST_URI": wsgi_encoding_dance(self.path), - # Non-standard, added by gunicorn - "RAW_URI": wsgi_encoding_dance(self.path), - "SERVER_NAME": self.server_name, - "SERVER_PORT": str(self.server_port), - "HTTP_HOST": self.host, - "SERVER_PROTOCOL": self.server_protocol, - "wsgi.version": self.wsgi_version, - "wsgi.url_scheme": self.url_scheme, - "wsgi.input": input_stream, - "wsgi.errors": self.errors_stream, - "wsgi.multithread": self.multithread, - "wsgi.multiprocess": self.multiprocess, - "wsgi.run_once": self.run_once, - } - ) - - headers = self.headers.copy() - - if content_type is not None: - result["CONTENT_TYPE"] = content_type - headers.set("Content-Type", content_type) - - if content_length is not None: - result["CONTENT_LENGTH"] = str(content_length) - headers.set("Content-Length", content_length) - - for key, value in headers.to_wsgi_list(): - result["HTTP_%s" % key.upper().replace("-", "_")] = value - - if self.environ_overrides: - result.update(self.environ_overrides) - - return result - - def get_request(self, cls=None): - """Returns a request with the data. If the request class is not - specified :attr:`request_class` is used. - - :param cls: The request wrapper to use. - """ - if cls is None: - cls = self.request_class - return cls(self.get_environ()) - - -class ClientRedirectError(Exception): - """If a redirect loop is detected when using follow_redirects=True with - the :cls:`Client`, then this exception is raised. - """ - - -class Client(object): - """This class allows you to send requests to a wrapped application. - - The response wrapper can be a class or factory function that takes - three arguments: app_iter, status and headers. The default response - wrapper just returns a tuple. - - Example:: - - class ClientResponse(BaseResponse): - ... - - client = Client(MyApplication(), response_wrapper=ClientResponse) - - The use_cookies parameter indicates whether cookies should be stored and - sent for subsequent requests. This is True by default, but passing False - will disable this behaviour. - - If you want to request some subdomain of your application you may set - `allow_subdomain_redirects` to `True` as if not no external redirects - are allowed. - - .. versionadded:: 0.5 - `use_cookies` is new in this version. Older versions did not provide - builtin cookie support. - - .. versionadded:: 0.14 - The `mimetype` parameter was added. - - .. versionadded:: 0.15 - The ``json`` parameter. - """ - - def __init__( - self, - application, - response_wrapper=None, - use_cookies=True, - allow_subdomain_redirects=False, - ): - self.application = application - self.response_wrapper = response_wrapper - if use_cookies: - self.cookie_jar = _TestCookieJar() - else: - self.cookie_jar = None - self.allow_subdomain_redirects = allow_subdomain_redirects - - def set_cookie( - self, - server_name, - key, - value="", - max_age=None, - expires=None, - path="/", - domain=None, - secure=None, - httponly=False, - samesite=None, - charset="utf-8", - ): - """Sets a cookie in the client's cookie jar. The server name - is required and has to match the one that is also passed to - the open call. - """ - assert self.cookie_jar is not None, "cookies disabled" - header = dump_cookie( - key, - value, - max_age, - expires, - path, - domain, - secure, - httponly, - charset, - samesite=samesite, - ) - environ = create_environ(path, base_url="http://" + server_name) - headers = [("Set-Cookie", header)] - self.cookie_jar.extract_wsgi(environ, headers) - - def delete_cookie(self, server_name, key, path="/", domain=None): - """Deletes a cookie in the test client.""" - self.set_cookie( - server_name, key, expires=0, max_age=0, path=path, domain=domain - ) - - def run_wsgi_app(self, environ, buffered=False): - """Runs the wrapped WSGI app with the given environment.""" - if self.cookie_jar is not None: - self.cookie_jar.inject_wsgi(environ) - rv = run_wsgi_app(self.application, environ, buffered=buffered) - if self.cookie_jar is not None: - self.cookie_jar.extract_wsgi(environ, rv[2]) - return rv - - def resolve_redirect(self, response, new_location, environ, buffered=False): - """Perform a new request to the location given by the redirect - response to the previous request. - """ - scheme, netloc, path, qs, anchor = url_parse(new_location) - builder = EnvironBuilder.from_environ(environ, query_string=qs) - - to_name_parts = netloc.split(":", 1)[0].split(".") - from_name_parts = builder.server_name.split(".") - - if to_name_parts != [""]: - # The new location has a host, use it for the base URL. - builder.url_scheme = scheme - builder.host = netloc - else: - # A local redirect with autocorrect_location_header=False - # doesn't have a host, so use the request's host. - to_name_parts = from_name_parts - - # Explain why a redirect to a different server name won't be followed. - if to_name_parts != from_name_parts: - if to_name_parts[-len(from_name_parts) :] == from_name_parts: - if not self.allow_subdomain_redirects: - raise RuntimeError("Following subdomain redirects is not enabled.") - else: - raise RuntimeError("Following external redirects is not supported.") - - path_parts = path.split("/") - root_parts = builder.script_root.split("/") - - if path_parts[: len(root_parts)] == root_parts: - # Strip the script root from the path. - builder.path = path[len(builder.script_root) :] - else: - # The new location is not under the script root, so use the - # whole path and clear the previous root. - builder.path = path - builder.script_root = "" - - status_code = int(response[1].split(None, 1)[0]) - - # Only 307 and 308 preserve all of the original request. - if status_code not in {307, 308}: - # HEAD is preserved, everything else becomes GET. - if builder.method != "HEAD": - builder.method = "GET" - - # Clear the body and the headers that describe it. - builder.input_stream = None - builder.content_type = None - builder.content_length = None - builder.headers.pop("Transfer-Encoding", None) - - # Disable the response wrapper while handling redirects. Not - # thread safe, but the client should not be shared anyway. - old_response_wrapper = self.response_wrapper - self.response_wrapper = None - - try: - return self.open(builder, as_tuple=True, buffered=buffered) - finally: - self.response_wrapper = old_response_wrapper - - def open(self, *args, **kwargs): - """Takes the same arguments as the :class:`EnvironBuilder` class with - some additions: You can provide a :class:`EnvironBuilder` or a WSGI - environment as only argument instead of the :class:`EnvironBuilder` - arguments and two optional keyword arguments (`as_tuple`, `buffered`) - that change the type of the return value or the way the application is - executed. - - .. versionchanged:: 0.5 - If a dict is provided as file in the dict for the `data` parameter - the content type has to be called `content_type` now instead of - `mimetype`. This change was made for consistency with - :class:`werkzeug.FileWrapper`. - - The `follow_redirects` parameter was added to :func:`open`. - - Additional parameters: - - :param as_tuple: Returns a tuple in the form ``(environ, result)`` - :param buffered: Set this to True to buffer the application run. - This will automatically close the application for - you as well. - :param follow_redirects: Set this to True if the `Client` should - follow HTTP redirects. - """ - as_tuple = kwargs.pop("as_tuple", False) - buffered = kwargs.pop("buffered", False) - follow_redirects = kwargs.pop("follow_redirects", False) - environ = None - if not kwargs and len(args) == 1: - if isinstance(args[0], EnvironBuilder): - environ = args[0].get_environ() - elif isinstance(args[0], dict): - environ = args[0] - if environ is None: - builder = EnvironBuilder(*args, **kwargs) - try: - environ = builder.get_environ() - finally: - builder.close() - - response = self.run_wsgi_app(environ.copy(), buffered=buffered) - - # handle redirects - redirect_chain = [] - while 1: - status_code = int(response[1].split(None, 1)[0]) - if ( - status_code not in {301, 302, 303, 305, 307, 308} - or not follow_redirects - ): - break - - # Exhaust intermediate response bodies to ensure middleware - # that returns an iterator runs any cleanup code. - if not buffered: - for _ in response[0]: - pass - - new_location = response[2]["location"] - new_redirect_entry = (new_location, status_code) - if new_redirect_entry in redirect_chain: - raise ClientRedirectError("loop detected") - redirect_chain.append(new_redirect_entry) - environ, response = self.resolve_redirect( - response, new_location, environ, buffered=buffered - ) - - if self.response_wrapper is not None: - response = self.response_wrapper(*response) - if as_tuple: - return environ, response - return response - - def get(self, *args, **kw): - """Like open but method is enforced to GET.""" - kw["method"] = "GET" - return self.open(*args, **kw) - - def patch(self, *args, **kw): - """Like open but method is enforced to PATCH.""" - kw["method"] = "PATCH" - return self.open(*args, **kw) - - def post(self, *args, **kw): - """Like open but method is enforced to POST.""" - kw["method"] = "POST" - return self.open(*args, **kw) - - def head(self, *args, **kw): - """Like open but method is enforced to HEAD.""" - kw["method"] = "HEAD" - return self.open(*args, **kw) - - def put(self, *args, **kw): - """Like open but method is enforced to PUT.""" - kw["method"] = "PUT" - return self.open(*args, **kw) - - def delete(self, *args, **kw): - """Like open but method is enforced to DELETE.""" - kw["method"] = "DELETE" - return self.open(*args, **kw) - - def options(self, *args, **kw): - """Like open but method is enforced to OPTIONS.""" - kw["method"] = "OPTIONS" - return self.open(*args, **kw) - - def trace(self, *args, **kw): - """Like open but method is enforced to TRACE.""" - kw["method"] = "TRACE" - return self.open(*args, **kw) - - def __repr__(self): - return "<%s %r>" % (self.__class__.__name__, self.application) - - -def create_environ(*args, **kwargs): - """Create a new WSGI environ dict based on the values passed. The first - parameter should be the path of the request which defaults to '/'. The - second one can either be an absolute path (in that case the host is - localhost:80) or a full path to the request with scheme, netloc port and - the path to the script. - - This accepts the same arguments as the :class:`EnvironBuilder` - constructor. - - .. versionchanged:: 0.5 - This function is now a thin wrapper over :class:`EnvironBuilder` which - was added in 0.5. The `headers`, `environ_base`, `environ_overrides` - and `charset` parameters were added. - """ - builder = EnvironBuilder(*args, **kwargs) - try: - return builder.get_environ() - finally: - builder.close() - - -def run_wsgi_app(app, environ, buffered=False): - """Return a tuple in the form (app_iter, status, headers) of the - application output. This works best if you pass it an application that - returns an iterator all the time. - - Sometimes applications may use the `write()` callable returned - by the `start_response` function. This tries to resolve such edge - cases automatically. But if you don't get the expected output you - should set `buffered` to `True` which enforces buffering. - - If passed an invalid WSGI application the behavior of this function is - undefined. Never pass non-conforming WSGI applications to this function. - - :param app: the application to execute. - :param buffered: set to `True` to enforce buffering. - :return: tuple in the form ``(app_iter, status, headers)`` - """ - environ = _get_environ(environ) - response = [] - buffer = [] - - def start_response(status, headers, exc_info=None): - if exc_info is not None: - reraise(*exc_info) - response[:] = [status, headers] - return buffer.append - - app_rv = app(environ, start_response) - close_func = getattr(app_rv, "close", None) - app_iter = iter(app_rv) - - # when buffering we emit the close call early and convert the - # application iterator into a regular list - if buffered: - try: - app_iter = list(app_iter) - finally: - if close_func is not None: - close_func() - - # otherwise we iterate the application iter until we have a response, chain - # the already received data with the already collected data and wrap it in - # a new `ClosingIterator` if we need to restore a `close` callable from the - # original return value. - else: - for item in app_iter: - buffer.append(item) - if response: - break - if buffer: - app_iter = chain(buffer, app_iter) - if close_func is not None and app_iter is not app_rv: - app_iter = ClosingIterator(app_iter, close_func) - - return app_iter, response[0], Headers(response[1]) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/testapp.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/testapp.py deleted file mode 100644 index 5ea8549..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/testapp.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.testapp - ~~~~~~~~~~~~~~~~ - - Provide a small test application that can be used to test a WSGI server - and check it for WSGI compliance. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import base64 -import os -import sys -from textwrap import wrap - -from . import __version__ as _werkzeug_version -from .utils import escape -from .wrappers import BaseRequest as Request -from .wrappers import BaseResponse as Response - -logo = Response( - base64.b64decode( - """ -R0lGODlhoACgAOMIAAEDACwpAEpCAGdgAJaKAM28AOnVAP3rAP///////// -//////////////////////yH5BAEKAAgALAAAAACgAKAAAAT+EMlJq704680R+F0ojmRpnuj0rWnrv -nB8rbRs33gu0bzu/0AObxgsGn3D5HHJbCUFyqZ0ukkSDlAidctNFg7gbI9LZlrBaHGtzAae0eloe25 -7w9EDOX2fst/xenyCIn5/gFqDiVVDV4aGeYiKkhSFjnCQY5OTlZaXgZp8nJ2ekaB0SQOjqphrpnOiq -ncEn65UsLGytLVmQ6m4sQazpbtLqL/HwpnER8bHyLrLOc3Oz8PRONPU1crXN9na263dMt/g4SzjMeX -m5yDpLqgG7OzJ4u8lT/P69ej3JPn69kHzN2OIAHkB9RUYSFCFQYQJFTIkCDBiwoXWGnowaLEjRm7+G -p9A7Hhx4rUkAUaSLJlxHMqVMD/aSycSZkyTplCqtGnRAM5NQ1Ly5OmzZc6gO4d6DGAUKA+hSocWYAo -SlM6oUWX2O/o0KdaVU5vuSQLAa0ADwQgMEMB2AIECZhVSnTno6spgbtXmHcBUrQACcc2FrTrWS8wAf -78cMFBgwIBgbN+qvTt3ayikRBk7BoyGAGABAdYyfdzRQGV3l4coxrqQ84GpUBmrdR3xNIDUPAKDBSA -ADIGDhhqTZIWaDcrVX8EsbNzbkvCOxG8bN5w8ly9H8jyTJHC6DFndQydbguh2e/ctZJFXRxMAqqPVA -tQH5E64SPr1f0zz7sQYjAHg0In+JQ11+N2B0XXBeeYZgBZFx4tqBToiTCPv0YBgQv8JqA6BEf6RhXx -w1ENhRBnWV8ctEX4Ul2zc3aVGcQNC2KElyTDYyYUWvShdjDyMOGMuFjqnII45aogPhz/CodUHFwaDx -lTgsaOjNyhGWJQd+lFoAGk8ObghI0kawg+EV5blH3dr+digkYuAGSaQZFHFz2P/cTaLmhF52QeSb45 -Jwxd+uSVGHlqOZpOeJpCFZ5J+rkAkFjQ0N1tah7JJSZUFNsrkeJUJMIBi8jyaEKIhKPomnC91Uo+NB -yyaJ5umnnpInIFh4t6ZSpGaAVmizqjpByDegYl8tPE0phCYrhcMWSv+uAqHfgH88ak5UXZmlKLVJhd -dj78s1Fxnzo6yUCrV6rrDOkluG+QzCAUTbCwf9SrmMLzK6p+OPHx7DF+bsfMRq7Ec61Av9i6GLw23r -idnZ+/OO0a99pbIrJkproCQMA17OPG6suq3cca5ruDfXCCDoS7BEdvmJn5otdqscn+uogRHHXs8cbh -EIfYaDY1AkrC0cqwcZpnM6ludx72x0p7Fo/hZAcpJDjax0UdHavMKAbiKltMWCF3xxh9k25N/Viud8 -ba78iCvUkt+V6BpwMlErmcgc502x+u1nSxJSJP9Mi52awD1V4yB/QHONsnU3L+A/zR4VL/indx/y64 -gqcj+qgTeweM86f0Qy1QVbvmWH1D9h+alqg254QD8HJXHvjQaGOqEqC22M54PcftZVKVSQG9jhkv7C -JyTyDoAJfPdu8v7DRZAxsP/ky9MJ3OL36DJfCFPASC3/aXlfLOOON9vGZZHydGf8LnxYJuuVIbl83y -Az5n/RPz07E+9+zw2A2ahz4HxHo9Kt79HTMx1Q7ma7zAzHgHqYH0SoZWyTuOLMiHwSfZDAQTn0ajk9 -YQqodnUYjByQZhZak9Wu4gYQsMyEpIOAOQKze8CmEF45KuAHTvIDOfHJNipwoHMuGHBnJElUoDmAyX -c2Qm/R8Ah/iILCCJOEokGowdhDYc/yoL+vpRGwyVSCWFYZNljkhEirGXsalWcAgOdeAdoXcktF2udb -qbUhjWyMQxYO01o6KYKOr6iK3fE4MaS+DsvBsGOBaMb0Y6IxADaJhFICaOLmiWTlDAnY1KzDG4ambL -cWBA8mUzjJsN2KjSaSXGqMCVXYpYkj33mcIApyhQf6YqgeNAmNvuC0t4CsDbSshZJkCS1eNisKqlyG -cF8G2JeiDX6tO6Mv0SmjCa3MFb0bJaGPMU0X7c8XcpvMaOQmCajwSeY9G0WqbBmKv34DsMIEztU6Y2 -KiDlFdt6jnCSqx7Dmt6XnqSKaFFHNO5+FmODxMCWBEaco77lNDGXBM0ECYB/+s7nKFdwSF5hgXumQe -EZ7amRg39RHy3zIjyRCykQh8Zo2iviRKyTDn/zx6EefptJj2Cw+Ep2FSc01U5ry4KLPYsTyWnVGnvb -UpyGlhjBUljyjHhWpf8OFaXwhp9O4T1gU9UeyPPa8A2l0p1kNqPXEVRm1AOs1oAGZU596t6SOR2mcB -Oco1srWtkaVrMUzIErrKri85keKqRQYX9VX0/eAUK1hrSu6HMEX3Qh2sCh0q0D2CtnUqS4hj62sE/z -aDs2Sg7MBS6xnQeooc2R2tC9YrKpEi9pLXfYXp20tDCpSP8rKlrD4axprb9u1Df5hSbz9QU0cRpfgn -kiIzwKucd0wsEHlLpe5yHXuc6FrNelOl7pY2+11kTWx7VpRu97dXA3DO1vbkhcb4zyvERYajQgAADs -=""" - ), - mimetype="image/png", -) - - -TEMPLATE = u"""\ - -WSGI Information - -
    - -

    WSGI Information

    -

    - This page displays all available information about the WSGI server and - the underlying Python interpreter. -

    Python Interpreter

    - - - - - - -
    Python Version - %(python_version)s -
    Platform - %(platform)s [%(os)s] -
    API Version - %(api_version)s -
    Byteorder - %(byteorder)s -
    Werkzeug Version - %(werkzeug_version)s -
    -

    WSGI Environment

    - %(wsgi_env)s
    -

    Installed Eggs

    -

    - The following python packages were installed on the system as - Python eggs: -

      %(python_eggs)s
    -

    System Path

    -

    - The following paths are the current contents of the load path. The - following entries are looked up for Python packages. Note that not - all items in this path are folders. Gray and underlined items are - entries pointing to invalid resources or used by custom import hooks - such as the zip importer. -

    - Items with a bright background were expanded for display from a relative - path. If you encounter such paths in the output you might want to check - your setup as relative paths are usually problematic in multithreaded - environments. -

      %(sys_path)s
    -
    -""" - - -def iter_sys_path(): - if os.name == "posix": - - def strip(x): - prefix = os.path.expanduser("~") - if x.startswith(prefix): - x = "~" + x[len(prefix) :] - return x - - else: - - def strip(x): - return x - - cwd = os.path.abspath(os.getcwd()) - for item in sys.path: - path = os.path.join(cwd, item or os.path.curdir) - yield strip(os.path.normpath(path)), not os.path.isdir(path), path != item - - -def render_testapp(req): - try: - import pkg_resources - except ImportError: - eggs = () - else: - eggs = sorted(pkg_resources.working_set, key=lambda x: x.project_name.lower()) - python_eggs = [] - for egg in eggs: - try: - version = egg.version - except (ValueError, AttributeError): - version = "unknown" - python_eggs.append( - "
  • %s [%s]" % (escape(egg.project_name), escape(version)) - ) - - wsgi_env = [] - sorted_environ = sorted(req.environ.items(), key=lambda x: repr(x[0]).lower()) - for key, value in sorted_environ: - wsgi_env.append( - "%s%s" - % (escape(str(key)), " ".join(wrap(escape(repr(value))))) - ) - - sys_path = [] - for item, virtual, expanded in iter_sys_path(): - class_ = [] - if virtual: - class_.append("virtual") - if expanded: - class_.append("exp") - sys_path.append( - "%s" - % (' class="%s"' % " ".join(class_) if class_ else "", escape(item)) - ) - - return ( - TEMPLATE - % { - "python_version": "
    ".join(escape(sys.version).splitlines()), - "platform": escape(sys.platform), - "os": escape(os.name), - "api_version": sys.api_version, - "byteorder": sys.byteorder, - "werkzeug_version": _werkzeug_version, - "python_eggs": "\n".join(python_eggs), - "wsgi_env": "\n".join(wsgi_env), - "sys_path": "\n".join(sys_path), - } - ).encode("utf-8") - - -def test_app(environ, start_response): - """Simple test application that dumps the environment. You can use - it to check if Werkzeug is working properly: - - .. sourcecode:: pycon - - >>> from werkzeug.serving import run_simple - >>> from werkzeug.testapp import test_app - >>> run_simple('localhost', 3000, test_app) - * Running on http://localhost:3000/ - - The application displays important information from the WSGI environment, - the Python interpreter and the installed libraries. - """ - req = Request(environ, populate_request=False) - if req.args.get("resource") == "logo": - response = logo - else: - response = Response(render_testapp(req), mimetype="text/html") - return response(environ, start_response) - - -if __name__ == "__main__": - from .serving import run_simple - - run_simple("localhost", 5000, test_app, use_reloader=True) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/urls.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/urls.py deleted file mode 100644 index d5e487b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/urls.py +++ /dev/null @@ -1,1138 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.urls - ~~~~~~~~~~~~~ - - ``werkzeug.urls`` used to provide several wrapper functions for Python 2 - urlparse, whose main purpose were to work around the behavior of the Py2 - stdlib and its lack of unicode support. While this was already a somewhat - inconvenient situation, it got even more complicated because Python 3's - ``urllib.parse`` actually does handle unicode properly. In other words, - this module would wrap two libraries with completely different behavior. So - now this module contains a 2-and-3-compatible backport of Python 3's - ``urllib.parse``, which is mostly API-compatible. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import os -import re -from collections import namedtuple - -from ._compat import fix_tuple_repr -from ._compat import implements_to_string -from ._compat import make_literal_wrapper -from ._compat import normalize_string_tuple -from ._compat import PY2 -from ._compat import text_type -from ._compat import to_native -from ._compat import to_unicode -from ._compat import try_coerce_native -from ._internal import _decode_idna -from ._internal import _encode_idna - -# A regular expression for what a valid schema looks like -_scheme_re = re.compile(r"^[a-zA-Z0-9+-.]+$") - -# Characters that are safe in any part of an URL. -_always_safe = frozenset( - bytearray( - b"abcdefghijklmnopqrstuvwxyz" - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" - b"0123456789" - b"-._~" - ) -) - -_hexdigits = "0123456789ABCDEFabcdef" -_hextobyte = dict( - ((a + b).encode(), int(a + b, 16)) for a in _hexdigits for b in _hexdigits -) -_bytetohex = [("%%%02X" % char).encode("ascii") for char in range(256)] - - -_URLTuple = fix_tuple_repr( - namedtuple("_URLTuple", ["scheme", "netloc", "path", "query", "fragment"]) -) - - -class BaseURL(_URLTuple): - """Superclass of :py:class:`URL` and :py:class:`BytesURL`.""" - - __slots__ = () - - def replace(self, **kwargs): - """Return an URL with the same values, except for those parameters - given new values by whichever keyword arguments are specified.""" - return self._replace(**kwargs) - - @property - def host(self): - """The host part of the URL if available, otherwise `None`. The - host is either the hostname or the IP address mentioned in the - URL. It will not contain the port. - """ - return self._split_host()[0] - - @property - def ascii_host(self): - """Works exactly like :attr:`host` but will return a result that - is restricted to ASCII. If it finds a netloc that is not ASCII - it will attempt to idna decode it. This is useful for socket - operations when the URL might include internationalized characters. - """ - rv = self.host - if rv is not None and isinstance(rv, text_type): - try: - rv = _encode_idna(rv) - except UnicodeError: - rv = rv.encode("ascii", "ignore") - return to_native(rv, "ascii", "ignore") - - @property - def port(self): - """The port in the URL as an integer if it was present, `None` - otherwise. This does not fill in default ports. - """ - try: - rv = int(to_native(self._split_host()[1])) - if 0 <= rv <= 65535: - return rv - except (ValueError, TypeError): - pass - - @property - def auth(self): - """The authentication part in the URL if available, `None` - otherwise. - """ - return self._split_netloc()[0] - - @property - def username(self): - """The username if it was part of the URL, `None` otherwise. - This undergoes URL decoding and will always be a unicode string. - """ - rv = self._split_auth()[0] - if rv is not None: - return _url_unquote_legacy(rv) - - @property - def raw_username(self): - """The username if it was part of the URL, `None` otherwise. - Unlike :attr:`username` this one is not being decoded. - """ - return self._split_auth()[0] - - @property - def password(self): - """The password if it was part of the URL, `None` otherwise. - This undergoes URL decoding and will always be a unicode string. - """ - rv = self._split_auth()[1] - if rv is not None: - return _url_unquote_legacy(rv) - - @property - def raw_password(self): - """The password if it was part of the URL, `None` otherwise. - Unlike :attr:`password` this one is not being decoded. - """ - return self._split_auth()[1] - - def decode_query(self, *args, **kwargs): - """Decodes the query part of the URL. Ths is a shortcut for - calling :func:`url_decode` on the query argument. The arguments and - keyword arguments are forwarded to :func:`url_decode` unchanged. - """ - return url_decode(self.query, *args, **kwargs) - - def join(self, *args, **kwargs): - """Joins this URL with another one. This is just a convenience - function for calling into :meth:`url_join` and then parsing the - return value again. - """ - return url_parse(url_join(self, *args, **kwargs)) - - def to_url(self): - """Returns a URL string or bytes depending on the type of the - information stored. This is just a convenience function - for calling :meth:`url_unparse` for this URL. - """ - return url_unparse(self) - - def decode_netloc(self): - """Decodes the netloc part into a string.""" - rv = _decode_idna(self.host or "") - - if ":" in rv: - rv = "[%s]" % rv - port = self.port - if port is not None: - rv = "%s:%d" % (rv, port) - auth = ":".join( - filter( - None, - [ - _url_unquote_legacy(self.raw_username or "", "/:%@"), - _url_unquote_legacy(self.raw_password or "", "/:%@"), - ], - ) - ) - if auth: - rv = "%s@%s" % (auth, rv) - return rv - - def to_uri_tuple(self): - """Returns a :class:`BytesURL` tuple that holds a URI. This will - encode all the information in the URL properly to ASCII using the - rules a web browser would follow. - - It's usually more interesting to directly call :meth:`iri_to_uri` which - will return a string. - """ - return url_parse(iri_to_uri(self).encode("ascii")) - - def to_iri_tuple(self): - """Returns a :class:`URL` tuple that holds a IRI. This will try - to decode as much information as possible in the URL without - losing information similar to how a web browser does it for the - URL bar. - - It's usually more interesting to directly call :meth:`uri_to_iri` which - will return a string. - """ - return url_parse(uri_to_iri(self)) - - def get_file_location(self, pathformat=None): - """Returns a tuple with the location of the file in the form - ``(server, location)``. If the netloc is empty in the URL or - points to localhost, it's represented as ``None``. - - The `pathformat` by default is autodetection but needs to be set - when working with URLs of a specific system. The supported values - are ``'windows'`` when working with Windows or DOS paths and - ``'posix'`` when working with posix paths. - - If the URL does not point to a local file, the server and location - are both represented as ``None``. - - :param pathformat: The expected format of the path component. - Currently ``'windows'`` and ``'posix'`` are - supported. Defaults to ``None`` which is - autodetect. - """ - if self.scheme != "file": - return None, None - - path = url_unquote(self.path) - host = self.netloc or None - - if pathformat is None: - if os.name == "nt": - pathformat = "windows" - else: - pathformat = "posix" - - if pathformat == "windows": - if path[:1] == "/" and path[1:2].isalpha() and path[2:3] in "|:": - path = path[1:2] + ":" + path[3:] - windows_share = path[:3] in ("\\" * 3, "/" * 3) - import ntpath - - path = ntpath.normpath(path) - # Windows shared drives are represented as ``\\host\\directory``. - # That results in a URL like ``file://///host/directory``, and a - # path like ``///host/directory``. We need to special-case this - # because the path contains the hostname. - if windows_share and host is None: - parts = path.lstrip("\\").split("\\", 1) - if len(parts) == 2: - host, path = parts - else: - host = parts[0] - path = "" - elif pathformat == "posix": - import posixpath - - path = posixpath.normpath(path) - else: - raise TypeError("Invalid path format %s" % repr(pathformat)) - - if host in ("127.0.0.1", "::1", "localhost"): - host = None - - return host, path - - def _split_netloc(self): - if self._at in self.netloc: - return self.netloc.split(self._at, 1) - return None, self.netloc - - def _split_auth(self): - auth = self._split_netloc()[0] - if not auth: - return None, None - if self._colon not in auth: - return auth, None - return auth.split(self._colon, 1) - - def _split_host(self): - rv = self._split_netloc()[1] - if not rv: - return None, None - - if not rv.startswith(self._lbracket): - if self._colon in rv: - return rv.split(self._colon, 1) - return rv, None - - idx = rv.find(self._rbracket) - if idx < 0: - return rv, None - - host = rv[1:idx] - rest = rv[idx + 1 :] - if rest.startswith(self._colon): - return host, rest[1:] - return host, None - - -@implements_to_string -class URL(BaseURL): - """Represents a parsed URL. This behaves like a regular tuple but - also has some extra attributes that give further insight into the - URL. - """ - - __slots__ = () - _at = "@" - _colon = ":" - _lbracket = "[" - _rbracket = "]" - - def __str__(self): - return self.to_url() - - def encode_netloc(self): - """Encodes the netloc part to an ASCII safe URL as bytes.""" - rv = self.ascii_host or "" - if ":" in rv: - rv = "[%s]" % rv - port = self.port - if port is not None: - rv = "%s:%d" % (rv, port) - auth = ":".join( - filter( - None, - [ - url_quote(self.raw_username or "", "utf-8", "strict", "/:%"), - url_quote(self.raw_password or "", "utf-8", "strict", "/:%"), - ], - ) - ) - if auth: - rv = "%s@%s" % (auth, rv) - return to_native(rv) - - def encode(self, charset="utf-8", errors="replace"): - """Encodes the URL to a tuple made out of bytes. The charset is - only being used for the path, query and fragment. - """ - return BytesURL( - self.scheme.encode("ascii"), - self.encode_netloc(), - self.path.encode(charset, errors), - self.query.encode(charset, errors), - self.fragment.encode(charset, errors), - ) - - -class BytesURL(BaseURL): - """Represents a parsed URL in bytes.""" - - __slots__ = () - _at = b"@" - _colon = b":" - _lbracket = b"[" - _rbracket = b"]" - - def __str__(self): - return self.to_url().decode("utf-8", "replace") - - def encode_netloc(self): - """Returns the netloc unchanged as bytes.""" - return self.netloc - - def decode(self, charset="utf-8", errors="replace"): - """Decodes the URL to a tuple made out of strings. The charset is - only being used for the path, query and fragment. - """ - return URL( - self.scheme.decode("ascii"), - self.decode_netloc(), - self.path.decode(charset, errors), - self.query.decode(charset, errors), - self.fragment.decode(charset, errors), - ) - - -_unquote_maps = {frozenset(): _hextobyte} - - -def _unquote_to_bytes(string, unsafe=""): - if isinstance(string, text_type): - string = string.encode("utf-8") - - if isinstance(unsafe, text_type): - unsafe = unsafe.encode("utf-8") - - unsafe = frozenset(bytearray(unsafe)) - groups = iter(string.split(b"%")) - result = bytearray(next(groups, b"")) - - try: - hex_to_byte = _unquote_maps[unsafe] - except KeyError: - hex_to_byte = _unquote_maps[unsafe] = { - h: b for h, b in _hextobyte.items() if b not in unsafe - } - - for group in groups: - code = group[:2] - - if code in hex_to_byte: - result.append(hex_to_byte[code]) - result.extend(group[2:]) - else: - result.append(37) # % - result.extend(group) - - return bytes(result) - - -def _url_encode_impl(obj, charset, encode_keys, sort, key): - from .datastructures import iter_multi_items - - iterable = iter_multi_items(obj) - if sort: - iterable = sorted(iterable, key=key) - for key, value in iterable: - if value is None: - continue - if not isinstance(key, bytes): - key = text_type(key).encode(charset) - if not isinstance(value, bytes): - value = text_type(value).encode(charset) - yield _fast_url_quote_plus(key) + "=" + _fast_url_quote_plus(value) - - -def _url_unquote_legacy(value, unsafe=""): - try: - return url_unquote(value, charset="utf-8", errors="strict", unsafe=unsafe) - except UnicodeError: - return url_unquote(value, charset="latin1", unsafe=unsafe) - - -def url_parse(url, scheme=None, allow_fragments=True): - """Parses a URL from a string into a :class:`URL` tuple. If the URL - is lacking a scheme it can be provided as second argument. Otherwise, - it is ignored. Optionally fragments can be stripped from the URL - by setting `allow_fragments` to `False`. - - The inverse of this function is :func:`url_unparse`. - - :param url: the URL to parse. - :param scheme: the default schema to use if the URL is schemaless. - :param allow_fragments: if set to `False` a fragment will be removed - from the URL. - """ - s = make_literal_wrapper(url) - is_text_based = isinstance(url, text_type) - - if scheme is None: - scheme = s("") - netloc = query = fragment = s("") - i = url.find(s(":")) - if i > 0 and _scheme_re.match(to_native(url[:i], errors="replace")): - # make sure "iri" is not actually a port number (in which case - # "scheme" is really part of the path) - rest = url[i + 1 :] - if not rest or any(c not in s("0123456789") for c in rest): - # not a port number - scheme, url = url[:i].lower(), rest - - if url[:2] == s("//"): - delim = len(url) - for c in s("/?#"): - wdelim = url.find(c, 2) - if wdelim >= 0: - delim = min(delim, wdelim) - netloc, url = url[2:delim], url[delim:] - if (s("[") in netloc and s("]") not in netloc) or ( - s("]") in netloc and s("[") not in netloc - ): - raise ValueError("Invalid IPv6 URL") - - if allow_fragments and s("#") in url: - url, fragment = url.split(s("#"), 1) - if s("?") in url: - url, query = url.split(s("?"), 1) - - result_type = URL if is_text_based else BytesURL - return result_type(scheme, netloc, url, query, fragment) - - -def _make_fast_url_quote(charset="utf-8", errors="strict", safe="/:", unsafe=""): - """Precompile the translation table for a URL encoding function. - - Unlike :func:`url_quote`, the generated function only takes the - string to quote. - - :param charset: The charset to encode the result with. - :param errors: How to handle encoding errors. - :param safe: An optional sequence of safe characters to never encode. - :param unsafe: An optional sequence of unsafe characters to always encode. - """ - if isinstance(safe, text_type): - safe = safe.encode(charset, errors) - - if isinstance(unsafe, text_type): - unsafe = unsafe.encode(charset, errors) - - safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) - table = [chr(c) if c in safe else "%%%02X" % c for c in range(256)] - - if not PY2: - - def quote(string): - return "".join([table[c] for c in string]) - - else: - - def quote(string): - return "".join([table[c] for c in bytearray(string)]) - - return quote - - -_fast_url_quote = _make_fast_url_quote() -_fast_quote_plus = _make_fast_url_quote(safe=" ", unsafe="+") - - -def _fast_url_quote_plus(string): - return _fast_quote_plus(string).replace(" ", "+") - - -def url_quote(string, charset="utf-8", errors="strict", safe="/:", unsafe=""): - """URL encode a single string with a given encoding. - - :param s: the string to quote. - :param charset: the charset to be used. - :param safe: an optional sequence of safe characters. - :param unsafe: an optional sequence of unsafe characters. - - .. versionadded:: 0.9.2 - The `unsafe` parameter was added. - """ - if not isinstance(string, (text_type, bytes, bytearray)): - string = text_type(string) - if isinstance(string, text_type): - string = string.encode(charset, errors) - if isinstance(safe, text_type): - safe = safe.encode(charset, errors) - if isinstance(unsafe, text_type): - unsafe = unsafe.encode(charset, errors) - safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) - rv = bytearray() - for char in bytearray(string): - if char in safe: - rv.append(char) - else: - rv.extend(_bytetohex[char]) - return to_native(bytes(rv)) - - -def url_quote_plus(string, charset="utf-8", errors="strict", safe=""): - """URL encode a single string with the given encoding and convert - whitespace to "+". - - :param s: The string to quote. - :param charset: The charset to be used. - :param safe: An optional sequence of safe characters. - """ - return url_quote(string, charset, errors, safe + " ", "+").replace(" ", "+") - - -def url_unparse(components): - """The reverse operation to :meth:`url_parse`. This accepts arbitrary - as well as :class:`URL` tuples and returns a URL as a string. - - :param components: the parsed URL as tuple which should be converted - into a URL string. - """ - scheme, netloc, path, query, fragment = normalize_string_tuple(components) - s = make_literal_wrapper(scheme) - url = s("") - - # We generally treat file:///x and file:/x the same which is also - # what browsers seem to do. This also allows us to ignore a schema - # register for netloc utilization or having to differentiate between - # empty and missing netloc. - if netloc or (scheme and path.startswith(s("/"))): - if path and path[:1] != s("/"): - path = s("/") + path - url = s("//") + (netloc or s("")) + path - elif path: - url += path - if scheme: - url = scheme + s(":") + url - if query: - url = url + s("?") + query - if fragment: - url = url + s("#") + fragment - return url - - -def url_unquote(string, charset="utf-8", errors="replace", unsafe=""): - """URL decode a single string with a given encoding. If the charset - is set to `None` no unicode decoding is performed and raw bytes - are returned. - - :param s: the string to unquote. - :param charset: the charset of the query string. If set to `None` - no unicode decoding will take place. - :param errors: the error handling for the charset decoding. - """ - rv = _unquote_to_bytes(string, unsafe) - if charset is not None: - rv = rv.decode(charset, errors) - return rv - - -def url_unquote_plus(s, charset="utf-8", errors="replace"): - """URL decode a single string with the given `charset` and decode "+" to - whitespace. - - Per default encoding errors are ignored. If you want a different behavior - you can set `errors` to ``'replace'`` or ``'strict'``. In strict mode a - :exc:`HTTPUnicodeError` is raised. - - :param s: The string to unquote. - :param charset: the charset of the query string. If set to `None` - no unicode decoding will take place. - :param errors: The error handling for the `charset` decoding. - """ - if isinstance(s, text_type): - s = s.replace(u"+", u" ") - else: - s = s.replace(b"+", b" ") - return url_unquote(s, charset, errors) - - -def url_fix(s, charset="utf-8"): - r"""Sometimes you get an URL by a user that just isn't a real URL because - it contains unsafe characters like ' ' and so on. This function can fix - some of the problems in a similar way browsers handle data entered by the - user: - - >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffskl\xe4rung)') - 'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)' - - :param s: the string with the URL to fix. - :param charset: The target charset for the URL if the url was given as - unicode string. - """ - # First step is to switch to unicode processing and to convert - # backslashes (which are invalid in URLs anyways) to slashes. This is - # consistent with what Chrome does. - s = to_unicode(s, charset, "replace").replace("\\", "/") - - # For the specific case that we look like a malformed windows URL - # we want to fix this up manually: - if s.startswith("file://") and s[7:8].isalpha() and s[8:10] in (":/", "|/"): - s = "file:///" + s[7:] - - url = url_parse(s) - path = url_quote(url.path, charset, safe="/%+$!*'(),") - qs = url_quote_plus(url.query, charset, safe=":&%=+$!*'(),") - anchor = url_quote_plus(url.fragment, charset, safe=":&%=+$!*'(),") - return to_native(url_unparse((url.scheme, url.encode_netloc(), path, qs, anchor))) - - -# not-unreserved characters remain quoted when unquoting to IRI -_to_iri_unsafe = "".join([chr(c) for c in range(128) if c not in _always_safe]) - - -def _codec_error_url_quote(e): - """Used in :func:`uri_to_iri` after unquoting to re-quote any - invalid bytes. - """ - out = _fast_url_quote(e.object[e.start : e.end]) - - if PY2: - out = out.decode("utf-8") - - return out, e.end - - -codecs.register_error("werkzeug.url_quote", _codec_error_url_quote) - - -def uri_to_iri(uri, charset="utf-8", errors="werkzeug.url_quote"): - """Convert a URI to an IRI. All valid UTF-8 characters are unquoted, - leaving all reserved and invalid characters quoted. If the URL has - a domain, it is decoded from Punycode. - - >>> uri_to_iri("http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF") - 'http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF' - - :param uri: The URI to convert. - :param charset: The encoding to encode unquoted bytes with. - :param errors: Error handler to use during ``bytes.encode``. By - default, invalid bytes are left quoted. - - .. versionchanged:: 0.15 - All reserved and invalid characters remain quoted. Previously, - only some reserved characters were preserved, and invalid bytes - were replaced instead of left quoted. - - .. versionadded:: 0.6 - """ - if isinstance(uri, tuple): - uri = url_unparse(uri) - - uri = url_parse(to_unicode(uri, charset)) - path = url_unquote(uri.path, charset, errors, _to_iri_unsafe) - query = url_unquote(uri.query, charset, errors, _to_iri_unsafe) - fragment = url_unquote(uri.fragment, charset, errors, _to_iri_unsafe) - return url_unparse((uri.scheme, uri.decode_netloc(), path, query, fragment)) - - -# reserved characters remain unquoted when quoting to URI -_to_uri_safe = ":/?#[]@!$&'()*+,;=%" - - -def iri_to_uri(iri, charset="utf-8", errors="strict", safe_conversion=False): - """Convert an IRI to a URI. All non-ASCII and unsafe characters are - quoted. If the URL has a domain, it is encoded to Punycode. - - >>> iri_to_uri('http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF') - 'http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF' - - :param iri: The IRI to convert. - :param charset: The encoding of the IRI. - :param errors: Error handler to use during ``bytes.encode``. - :param safe_conversion: Return the URL unchanged if it only contains - ASCII characters and no whitespace. See the explanation below. - - There is a general problem with IRI conversion with some protocols - that are in violation of the URI specification. Consider the - following two IRIs:: - - magnet:?xt=uri:whatever - itms-services://?action=download-manifest - - After parsing, we don't know if the scheme requires the ``//``, - which is dropped if empty, but conveys different meanings in the - final URL if it's present or not. In this case, you can use - ``safe_conversion``, which will return the URL unchanged if it only - contains ASCII characters and no whitespace. This can result in a - URI with unquoted characters if it was not already quoted correctly, - but preserves the URL's semantics. Werkzeug uses this for the - ``Location`` header for redirects. - - .. versionchanged:: 0.15 - All reserved characters remain unquoted. Previously, only some - reserved characters were left unquoted. - - .. versionchanged:: 0.9.6 - The ``safe_conversion`` parameter was added. - - .. versionadded:: 0.6 - """ - if isinstance(iri, tuple): - iri = url_unparse(iri) - - if safe_conversion: - # If we're not sure if it's safe to convert the URL, and it only - # contains ASCII characters, return it unconverted. - try: - native_iri = to_native(iri) - ascii_iri = native_iri.encode("ascii") - - # Only return if it doesn't have whitespace. (Why?) - if len(ascii_iri.split()) == 1: - return native_iri - except UnicodeError: - pass - - iri = url_parse(to_unicode(iri, charset, errors)) - path = url_quote(iri.path, charset, errors, _to_uri_safe) - query = url_quote(iri.query, charset, errors, _to_uri_safe) - fragment = url_quote(iri.fragment, charset, errors, _to_uri_safe) - return to_native( - url_unparse((iri.scheme, iri.encode_netloc(), path, query, fragment)) - ) - - -def url_decode( - s, - charset="utf-8", - decode_keys=False, - include_empty=True, - errors="replace", - separator="&", - cls=None, -): - """ - Parse a querystring and return it as :class:`MultiDict`. There is a - difference in key decoding on different Python versions. On Python 3 - keys will always be fully decoded whereas on Python 2, keys will - remain bytestrings if they fit into ASCII. On 2.x keys can be forced - to be unicode by setting `decode_keys` to `True`. - - If the charset is set to `None` no unicode decoding will happen and - raw bytes will be returned. - - Per default a missing value for a key will default to an empty key. If - you don't want that behavior you can set `include_empty` to `False`. - - Per default encoding errors are ignored. If you want a different behavior - you can set `errors` to ``'replace'`` or ``'strict'``. In strict mode a - `HTTPUnicodeError` is raised. - - .. versionchanged:: 0.5 - In previous versions ";" and "&" could be used for url decoding. - This changed in 0.5 where only "&" is supported. If you want to - use ";" instead a different `separator` can be provided. - - The `cls` parameter was added. - - :param s: a string with the query string to decode. - :param charset: the charset of the query string. If set to `None` - no unicode decoding will take place. - :param decode_keys: Used on Python 2.x to control whether keys should - be forced to be unicode objects. If set to `True` - then keys will be unicode in all cases. Otherwise, - they remain `str` if they fit into ASCII. - :param include_empty: Set to `False` if you don't want empty values to - appear in the dict. - :param errors: the decoding error behavior. - :param separator: the pair separator to be used, defaults to ``&`` - :param cls: an optional dict class to use. If this is not specified - or `None` the default :class:`MultiDict` is used. - """ - if cls is None: - from .datastructures import MultiDict - - cls = MultiDict - if isinstance(s, text_type) and not isinstance(separator, text_type): - separator = separator.decode(charset or "ascii") - elif isinstance(s, bytes) and not isinstance(separator, bytes): - separator = separator.encode(charset or "ascii") - return cls( - _url_decode_impl( - s.split(separator), charset, decode_keys, include_empty, errors - ) - ) - - -def url_decode_stream( - stream, - charset="utf-8", - decode_keys=False, - include_empty=True, - errors="replace", - separator="&", - cls=None, - limit=None, - return_iterator=False, -): - """Works like :func:`url_decode` but decodes a stream. The behavior - of stream and limit follows functions like - :func:`~werkzeug.wsgi.make_line_iter`. The generator of pairs is - directly fed to the `cls` so you can consume the data while it's - parsed. - - .. versionadded:: 0.8 - - :param stream: a stream with the encoded querystring - :param charset: the charset of the query string. If set to `None` - no unicode decoding will take place. - :param decode_keys: Used on Python 2.x to control whether keys should - be forced to be unicode objects. If set to `True`, - keys will be unicode in all cases. Otherwise, they - remain `str` if they fit into ASCII. - :param include_empty: Set to `False` if you don't want empty values to - appear in the dict. - :param errors: the decoding error behavior. - :param separator: the pair separator to be used, defaults to ``&`` - :param cls: an optional dict class to use. If this is not specified - or `None` the default :class:`MultiDict` is used. - :param limit: the content length of the URL data. Not necessary if - a limited stream is provided. - :param return_iterator: if set to `True` the `cls` argument is ignored - and an iterator over all decoded pairs is - returned - """ - from .wsgi import make_chunk_iter - - pair_iter = make_chunk_iter(stream, separator, limit) - decoder = _url_decode_impl(pair_iter, charset, decode_keys, include_empty, errors) - - if return_iterator: - return decoder - - if cls is None: - from .datastructures import MultiDict - - cls = MultiDict - - return cls(decoder) - - -def _url_decode_impl(pair_iter, charset, decode_keys, include_empty, errors): - for pair in pair_iter: - if not pair: - continue - s = make_literal_wrapper(pair) - equal = s("=") - if equal in pair: - key, value = pair.split(equal, 1) - else: - if not include_empty: - continue - key = pair - value = s("") - key = url_unquote_plus(key, charset, errors) - if charset is not None and PY2 and not decode_keys: - key = try_coerce_native(key) - yield key, url_unquote_plus(value, charset, errors) - - -def url_encode( - obj, charset="utf-8", encode_keys=False, sort=False, key=None, separator=b"&" -): - """URL encode a dict/`MultiDict`. If a value is `None` it will not appear - in the result string. Per default only values are encoded into the target - charset strings. If `encode_keys` is set to ``True`` unicode keys are - supported too. - - If `sort` is set to `True` the items are sorted by `key` or the default - sorting algorithm. - - .. versionadded:: 0.5 - `sort`, `key`, and `separator` were added. - - :param obj: the object to encode into a query string. - :param charset: the charset of the query string. - :param encode_keys: set to `True` if you have unicode keys. (Ignored on - Python 3.x) - :param sort: set to `True` if you want parameters to be sorted by `key`. - :param separator: the separator to be used for the pairs. - :param key: an optional function to be used for sorting. For more details - check out the :func:`sorted` documentation. - """ - separator = to_native(separator, "ascii") - return separator.join(_url_encode_impl(obj, charset, encode_keys, sort, key)) - - -def url_encode_stream( - obj, - stream=None, - charset="utf-8", - encode_keys=False, - sort=False, - key=None, - separator=b"&", -): - """Like :meth:`url_encode` but writes the results to a stream - object. If the stream is `None` a generator over all encoded - pairs is returned. - - .. versionadded:: 0.8 - - :param obj: the object to encode into a query string. - :param stream: a stream to write the encoded object into or `None` if - an iterator over the encoded pairs should be returned. In - that case the separator argument is ignored. - :param charset: the charset of the query string. - :param encode_keys: set to `True` if you have unicode keys. (Ignored on - Python 3.x) - :param sort: set to `True` if you want parameters to be sorted by `key`. - :param separator: the separator to be used for the pairs. - :param key: an optional function to be used for sorting. For more details - check out the :func:`sorted` documentation. - """ - separator = to_native(separator, "ascii") - gen = _url_encode_impl(obj, charset, encode_keys, sort, key) - if stream is None: - return gen - for idx, chunk in enumerate(gen): - if idx: - stream.write(separator) - stream.write(chunk) - - -def url_join(base, url, allow_fragments=True): - """Join a base URL and a possibly relative URL to form an absolute - interpretation of the latter. - - :param base: the base URL for the join operation. - :param url: the URL to join. - :param allow_fragments: indicates whether fragments should be allowed. - """ - if isinstance(base, tuple): - base = url_unparse(base) - if isinstance(url, tuple): - url = url_unparse(url) - - base, url = normalize_string_tuple((base, url)) - s = make_literal_wrapper(base) - - if not base: - return url - if not url: - return base - - bscheme, bnetloc, bpath, bquery, bfragment = url_parse( - base, allow_fragments=allow_fragments - ) - scheme, netloc, path, query, fragment = url_parse(url, bscheme, allow_fragments) - if scheme != bscheme: - return url - if netloc: - return url_unparse((scheme, netloc, path, query, fragment)) - netloc = bnetloc - - if path[:1] == s("/"): - segments = path.split(s("/")) - elif not path: - segments = bpath.split(s("/")) - if not query: - query = bquery - else: - segments = bpath.split(s("/"))[:-1] + path.split(s("/")) - - # If the rightmost part is "./" we want to keep the slash but - # remove the dot. - if segments[-1] == s("."): - segments[-1] = s("") - - # Resolve ".." and "." - segments = [segment for segment in segments if segment != s(".")] - while 1: - i = 1 - n = len(segments) - 1 - while i < n: - if segments[i] == s("..") and segments[i - 1] not in (s(""), s("..")): - del segments[i - 1 : i + 1] - break - i += 1 - else: - break - - # Remove trailing ".." if the URL is absolute - unwanted_marker = [s(""), s("..")] - while segments[:2] == unwanted_marker: - del segments[1] - - path = s("/").join(segments) - return url_unparse((scheme, netloc, path, query, fragment)) - - -class Href(object): - """Implements a callable that constructs URLs with the given base. The - function can be called with any number of positional and keyword - arguments which than are used to assemble the URL. Works with URLs - and posix paths. - - Positional arguments are appended as individual segments to - the path of the URL: - - >>> href = Href('/foo') - >>> href('bar', 23) - '/foo/bar/23' - >>> href('foo', bar=23) - '/foo/foo?bar=23' - - If any of the arguments (positional or keyword) evaluates to `None` it - will be skipped. If no keyword arguments are given the last argument - can be a :class:`dict` or :class:`MultiDict` (or any other dict subclass), - otherwise the keyword arguments are used for the query parameters, cutting - off the first trailing underscore of the parameter name: - - >>> href(is_=42) - '/foo?is=42' - >>> href({'foo': 'bar'}) - '/foo?foo=bar' - - Combining of both methods is not allowed: - - >>> href({'foo': 'bar'}, bar=42) - Traceback (most recent call last): - ... - TypeError: keyword arguments and query-dicts can't be combined - - Accessing attributes on the href object creates a new href object with - the attribute name as prefix: - - >>> bar_href = href.bar - >>> bar_href("blub") - '/foo/bar/blub' - - If `sort` is set to `True` the items are sorted by `key` or the default - sorting algorithm: - - >>> href = Href("/", sort=True) - >>> href(a=1, b=2, c=3) - '/?a=1&b=2&c=3' - - .. versionadded:: 0.5 - `sort` and `key` were added. - """ - - def __init__(self, base="./", charset="utf-8", sort=False, key=None): - if not base: - base = "./" - self.base = base - self.charset = charset - self.sort = sort - self.key = key - - def __getattr__(self, name): - if name[:2] == "__": - raise AttributeError(name) - base = self.base - if base[-1:] != "/": - base += "/" - return Href(url_join(base, name), self.charset, self.sort, self.key) - - def __call__(self, *path, **query): - if path and isinstance(path[-1], dict): - if query: - raise TypeError("keyword arguments and query-dicts can't be combined") - query, path = path[-1], path[:-1] - elif query: - query = dict( - [(k.endswith("_") and k[:-1] or k, v) for k, v in query.items()] - ) - path = "/".join( - [ - to_unicode(url_quote(x, self.charset), "ascii") - for x in path - if x is not None - ] - ).lstrip("/") - rv = self.base - if path: - if not rv.endswith("/"): - rv += "/" - rv = url_join(rv, "./" + path) - if query: - rv += "?" + to_unicode( - url_encode(query, self.charset, sort=self.sort, key=self.key), "ascii" - ) - return to_native(rv) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/useragents.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/useragents.py deleted file mode 100644 index 6ef6e2b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/useragents.py +++ /dev/null @@ -1,202 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.useragents - ~~~~~~~~~~~~~~~~~~~ - - This module provides a helper to inspect user agent strings. This module - is far from complete but should work for most of the currently available - browsers. - - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import re - - -class UserAgentParser(object): - """A simple user agent parser. Used by the `UserAgent`.""" - - platforms = ( - (" cros ", "chromeos"), - ("iphone|ios", "iphone"), - ("ipad", "ipad"), - (r"darwin|mac|os\s*x", "macos"), - ("win", "windows"), - (r"android", "android"), - ("netbsd", "netbsd"), - ("openbsd", "openbsd"), - ("freebsd", "freebsd"), - ("dragonfly", "dragonflybsd"), - ("(sun|i86)os", "solaris"), - (r"x11|lin(\b|ux)?", "linux"), - (r"nintendo\s+wii", "wii"), - ("irix", "irix"), - ("hp-?ux", "hpux"), - ("aix", "aix"), - ("sco|unix_sv", "sco"), - ("bsd", "bsd"), - ("amiga", "amiga"), - ("blackberry|playbook", "blackberry"), - ("symbian", "symbian"), - ) - browsers = ( - ("googlebot", "google"), - ("msnbot", "msn"), - ("yahoo", "yahoo"), - ("ask jeeves", "ask"), - (r"aol|america\s+online\s+browser", "aol"), - (r"opera|opr", "opera"), - ("edge", "edge"), - ("chrome|crios", "chrome"), - ("seamonkey", "seamonkey"), - ("firefox|firebird|phoenix|iceweasel", "firefox"), - ("galeon", "galeon"), - ("safari|version", "safari"), - ("webkit", "webkit"), - ("camino", "camino"), - ("konqueror", "konqueror"), - ("k-meleon", "kmeleon"), - ("netscape", "netscape"), - (r"msie|microsoft\s+internet\s+explorer|trident/.+? rv:", "msie"), - ("lynx", "lynx"), - ("links", "links"), - ("Baiduspider", "baidu"), - ("bingbot", "bing"), - ("mozilla", "mozilla"), - ) - - _browser_version_re = r"(?:%s)[/\sa-z(]*(\d+[.\da-z]+)?" - _language_re = re.compile( - r"(?:;\s*|\s+)(\b\w{2}\b(?:-\b\w{2}\b)?)\s*;|" - r"(?:\(|\[|;)\s*(\b\w{2}\b(?:-\b\w{2}\b)?)\s*(?:\]|\)|;)" - ) - - def __init__(self): - self.platforms = [(b, re.compile(a, re.I)) for a, b in self.platforms] - self.browsers = [ - (b, re.compile(self._browser_version_re % a, re.I)) - for a, b in self.browsers - ] - - def __call__(self, user_agent): - for platform, regex in self.platforms: # noqa: B007 - match = regex.search(user_agent) - if match is not None: - break - else: - platform = None - for browser, regex in self.browsers: # noqa: B007 - match = regex.search(user_agent) - if match is not None: - version = match.group(1) - break - else: - browser = version = None - match = self._language_re.search(user_agent) - if match is not None: - language = match.group(1) or match.group(2) - else: - language = None - return platform, browser, version, language - - -class UserAgent(object): - """Represents a user agent. Pass it a WSGI environment or a user agent - string and you can inspect some of the details from the user agent - string via the attributes. The following attributes exist: - - .. attribute:: string - - the raw user agent string - - .. attribute:: platform - - the browser platform. ``None`` if not recognized. - The following platforms are currently recognized: - - - `aix` - - `amiga` - - `android` - - `blackberry` - - `bsd` - - `chromeos` - - `dragonflybsd` - - `freebsd` - - `hpux` - - `ipad` - - `iphone` - - `irix` - - `linux` - - `macos` - - `netbsd` - - `openbsd` - - `sco` - - `solaris` - - `symbian` - - `wii` - - `windows` - - .. attribute:: browser - - the name of the browser. ``None`` if not recognized. - The following browsers are currently recognized: - - - `aol` * - - `ask` * - - `baidu` * - - `bing` * - - `camino` - - `chrome` - - `edge` - - `firefox` - - `galeon` - - `google` * - - `kmeleon` - - `konqueror` - - `links` - - `lynx` - - `mozilla` - - `msie` - - `msn` - - `netscape` - - `opera` - - `safari` - - `seamonkey` - - `webkit` - - `yahoo` * - - (Browsers marked with a star (``*``) are crawlers.) - - .. attribute:: version - - the version of the browser. ``None`` if not recognized. - - .. attribute:: language - - the language of the browser. ``None`` if not recognized. - """ - - _parser = UserAgentParser() - - def __init__(self, environ_or_string): - if isinstance(environ_or_string, dict): - environ_or_string = environ_or_string.get("HTTP_USER_AGENT", "") - self.string = environ_or_string - self.platform, self.browser, self.version, self.language = self._parser( - environ_or_string - ) - - def to_header(self): - return self.string - - def __str__(self): - return self.string - - def __nonzero__(self): - return bool(self.browser) - - __bool__ = __nonzero__ - - def __repr__(self): - return "<%s %r/%s>" % (self.__class__.__name__, self.browser, self.version) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/utils.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/utils.py deleted file mode 100644 index 59c6f27..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/utils.py +++ /dev/null @@ -1,778 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.utils - ~~~~~~~~~~~~~~ - - This module implements various utilities for WSGI applications. Most of - them are used by the request and response wrappers but especially for - middleware development it makes sense to use them without the wrappers. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import codecs -import os -import pkgutil -import re -import sys - -from ._compat import iteritems -from ._compat import PY2 -from ._compat import reraise -from ._compat import string_types -from ._compat import text_type -from ._compat import unichr -from ._internal import _DictAccessorProperty -from ._internal import _missing -from ._internal import _parse_signature - -try: - from html.entities import name2codepoint -except ImportError: - from htmlentitydefs import name2codepoint - - -_format_re = re.compile(r"\$(?:(%s)|\{(%s)\})" % (("[a-zA-Z_][a-zA-Z0-9_]*",) * 2)) -_entity_re = re.compile(r"&([^;]+);") -_filename_ascii_strip_re = re.compile(r"[^A-Za-z0-9_.-]") -_windows_device_files = ( - "CON", - "AUX", - "COM1", - "COM2", - "COM3", - "COM4", - "LPT1", - "LPT2", - "LPT3", - "PRN", - "NUL", -) - - -class cached_property(property): - """A decorator that converts a function into a lazy property. The - function wrapped is called the first time to retrieve the result - and then that calculated result is used the next time you access - the value:: - - class Foo(object): - - @cached_property - def foo(self): - # calculate something important here - return 42 - - The class has to have a `__dict__` in order for this property to - work. - """ - - # implementation detail: A subclass of python's builtin property - # decorator, we override __get__ to check for a cached value. If one - # chooses to invoke __get__ by hand the property will still work as - # expected because the lookup logic is replicated in __get__ for - # manual invocation. - - def __init__(self, func, name=None, doc=None): - self.__name__ = name or func.__name__ - self.__module__ = func.__module__ - self.__doc__ = doc or func.__doc__ - self.func = func - - def __set__(self, obj, value): - obj.__dict__[self.__name__] = value - - def __get__(self, obj, type=None): - if obj is None: - return self - value = obj.__dict__.get(self.__name__, _missing) - if value is _missing: - value = self.func(obj) - obj.__dict__[self.__name__] = value - return value - - -def invalidate_cached_property(obj, name): - """Invalidates the cache for a :class:`cached_property`: - - >>> class Test(object): - ... @cached_property - ... def magic_number(self): - ... print("recalculating...") - ... return 42 - ... - >>> var = Test() - >>> var.magic_number - recalculating... - 42 - >>> var.magic_number - 42 - >>> invalidate_cached_property(var, "magic_number") - >>> var.magic_number - recalculating... - 42 - - You must pass the name of the cached property as the second argument. - """ - if not isinstance(getattr(obj.__class__, name, None), cached_property): - raise TypeError( - "Attribute {} of object {} is not a cached_property, " - "cannot be invalidated".format(name, obj) - ) - obj.__dict__[name] = _missing - - -class environ_property(_DictAccessorProperty): - """Maps request attributes to environment variables. This works not only - for the Werzeug request object, but also any other class with an - environ attribute: - - >>> class Test(object): - ... environ = {'key': 'value'} - ... test = environ_property('key') - >>> var = Test() - >>> var.test - 'value' - - If you pass it a second value it's used as default if the key does not - exist, the third one can be a converter that takes a value and converts - it. If it raises :exc:`ValueError` or :exc:`TypeError` the default value - is used. If no default value is provided `None` is used. - - Per default the property is read only. You have to explicitly enable it - by passing ``read_only=False`` to the constructor. - """ - - read_only = True - - def lookup(self, obj): - return obj.environ - - -class header_property(_DictAccessorProperty): - """Like `environ_property` but for headers.""" - - def lookup(self, obj): - return obj.headers - - -class HTMLBuilder(object): - """Helper object for HTML generation. - - Per default there are two instances of that class. The `html` one, and - the `xhtml` one for those two dialects. The class uses keyword parameters - and positional parameters to generate small snippets of HTML. - - Keyword parameters are converted to XML/SGML attributes, positional - arguments are used as children. Because Python accepts positional - arguments before keyword arguments it's a good idea to use a list with the - star-syntax for some children: - - >>> html.p(class_='foo', *[html.a('foo', href='foo.html'), ' ', - ... html.a('bar', href='bar.html')]) - u'

    foo bar

    ' - - This class works around some browser limitations and can not be used for - arbitrary SGML/XML generation. For that purpose lxml and similar - libraries exist. - - Calling the builder escapes the string passed: - - >>> html.p(html("")) - u'

    <foo>

    ' - """ - - _entity_re = re.compile(r"&([^;]+);") - _entities = name2codepoint.copy() - _entities["apos"] = 39 - _empty_elements = { - "area", - "base", - "basefont", - "br", - "col", - "command", - "embed", - "frame", - "hr", - "img", - "input", - "keygen", - "isindex", - "link", - "meta", - "param", - "source", - "wbr", - } - _boolean_attributes = { - "selected", - "checked", - "compact", - "declare", - "defer", - "disabled", - "ismap", - "multiple", - "nohref", - "noresize", - "noshade", - "nowrap", - } - _plaintext_elements = {"textarea"} - _c_like_cdata = {"script", "style"} - - def __init__(self, dialect): - self._dialect = dialect - - def __call__(self, s): - return escape(s) - - def __getattr__(self, tag): - if tag[:2] == "__": - raise AttributeError(tag) - - def proxy(*children, **arguments): - buffer = "<" + tag - for key, value in iteritems(arguments): - if value is None: - continue - if key[-1] == "_": - key = key[:-1] - if key in self._boolean_attributes: - if not value: - continue - if self._dialect == "xhtml": - value = '="' + key + '"' - else: - value = "" - else: - value = '="' + escape(value) + '"' - buffer += " " + key + value - if not children and tag in self._empty_elements: - if self._dialect == "xhtml": - buffer += " />" - else: - buffer += ">" - return buffer - buffer += ">" - - children_as_string = "".join( - [text_type(x) for x in children if x is not None] - ) - - if children_as_string: - if tag in self._plaintext_elements: - children_as_string = escape(children_as_string) - elif tag in self._c_like_cdata and self._dialect == "xhtml": - children_as_string = ( - "/**/" - ) - buffer += children_as_string + "" - return buffer - - return proxy - - def __repr__(self): - return "<%s for %r>" % (self.__class__.__name__, self._dialect) - - -html = HTMLBuilder("html") -xhtml = HTMLBuilder("xhtml") - -# https://cgit.freedesktop.org/xdg/shared-mime-info/tree/freedesktop.org.xml.in -# https://www.iana.org/assignments/media-types/media-types.xhtml -# Types listed in the XDG mime info that have a charset in the IANA registration. -_charset_mimetypes = { - "application/ecmascript", - "application/javascript", - "application/sql", - "application/xml", - "application/xml-dtd", - "application/xml-external-parsed-entity", -} - - -def get_content_type(mimetype, charset): - """Returns the full content type string with charset for a mimetype. - - If the mimetype represents text, the charset parameter will be - appended, otherwise the mimetype is returned unchanged. - - :param mimetype: The mimetype to be used as content type. - :param charset: The charset to be appended for text mimetypes. - :return: The content type. - - .. versionchanged:: 0.15 - Any type that ends with ``+xml`` gets a charset, not just those - that start with ``application/``. Known text types such as - ``application/javascript`` are also given charsets. - """ - if ( - mimetype.startswith("text/") - or mimetype in _charset_mimetypes - or mimetype.endswith("+xml") - ): - mimetype += "; charset=" + charset - - return mimetype - - -def detect_utf_encoding(data): - """Detect which UTF encoding was used to encode the given bytes. - - The latest JSON standard (:rfc:`8259`) suggests that only UTF-8 is - accepted. Older documents allowed 8, 16, or 32. 16 and 32 can be big - or little endian. Some editors or libraries may prepend a BOM. - - :internal: - - :param data: Bytes in unknown UTF encoding. - :return: UTF encoding name - - .. versionadded:: 0.15 - """ - head = data[:4] - - if head[:3] == codecs.BOM_UTF8: - return "utf-8-sig" - - if b"\x00" not in head: - return "utf-8" - - if head in (codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE): - return "utf-32" - - if head[:2] in (codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE): - return "utf-16" - - if len(head) == 4: - if head[:3] == b"\x00\x00\x00": - return "utf-32-be" - - if head[::2] == b"\x00\x00": - return "utf-16-be" - - if head[1:] == b"\x00\x00\x00": - return "utf-32-le" - - if head[1::2] == b"\x00\x00": - return "utf-16-le" - - if len(head) == 2: - return "utf-16-be" if head.startswith(b"\x00") else "utf-16-le" - - return "utf-8" - - -def format_string(string, context): - """String-template format a string: - - >>> format_string('$foo and ${foo}s', dict(foo=42)) - '42 and 42s' - - This does not do any attribute lookup etc. For more advanced string - formattings have a look at the `werkzeug.template` module. - - :param string: the format string. - :param context: a dict with the variables to insert. - """ - - def lookup_arg(match): - x = context[match.group(1) or match.group(2)] - if not isinstance(x, string_types): - x = type(string)(x) - return x - - return _format_re.sub(lookup_arg, string) - - -def secure_filename(filename): - r"""Pass it a filename and it will return a secure version of it. This - filename can then safely be stored on a regular file system and passed - to :func:`os.path.join`. The filename returned is an ASCII only string - for maximum portability. - - On windows systems the function also makes sure that the file is not - named after one of the special device files. - - >>> secure_filename("My cool movie.mov") - 'My_cool_movie.mov' - >>> secure_filename("../../../etc/passwd") - 'etc_passwd' - >>> secure_filename(u'i contain cool \xfcml\xe4uts.txt') - 'i_contain_cool_umlauts.txt' - - The function might return an empty filename. It's your responsibility - to ensure that the filename is unique and that you abort or - generate a random filename if the function returned an empty one. - - .. versionadded:: 0.5 - - :param filename: the filename to secure - """ - if isinstance(filename, text_type): - from unicodedata import normalize - - filename = normalize("NFKD", filename).encode("ascii", "ignore") - if not PY2: - filename = filename.decode("ascii") - for sep in os.path.sep, os.path.altsep: - if sep: - filename = filename.replace(sep, " ") - filename = str(_filename_ascii_strip_re.sub("", "_".join(filename.split()))).strip( - "._" - ) - - # on nt a couple of special files are present in each folder. We - # have to ensure that the target file is not such a filename. In - # this case we prepend an underline - if ( - os.name == "nt" - and filename - and filename.split(".")[0].upper() in _windows_device_files - ): - filename = "_" + filename - - return filename - - -def escape(s): - """Replace special characters "&", "<", ">" and (") to HTML-safe sequences. - - There is a special handling for `None` which escapes to an empty string. - - .. versionchanged:: 0.9 - `quote` is now implicitly on. - - :param s: the string to escape. - :param quote: ignored. - """ - if s is None: - return "" - elif hasattr(s, "__html__"): - return text_type(s.__html__()) - - if not isinstance(s, string_types): - s = text_type(s) - - return ( - s.replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace('"', """) - ) - - -def unescape(s): - """The reverse function of `escape`. This unescapes all the HTML - entities, not only the XML entities inserted by `escape`. - - :param s: the string to unescape. - """ - - def handle_match(m): - name = m.group(1) - if name in HTMLBuilder._entities: - return unichr(HTMLBuilder._entities[name]) - try: - if name[:2] in ("#x", "#X"): - return unichr(int(name[2:], 16)) - elif name.startswith("#"): - return unichr(int(name[1:])) - except ValueError: - pass - return u"" - - return _entity_re.sub(handle_match, s) - - -def redirect(location, code=302, Response=None): - """Returns a response object (a WSGI application) that, if called, - redirects the client to the target location. Supported codes are - 301, 302, 303, 305, 307, and 308. 300 is not supported because - it's not a real redirect and 304 because it's the answer for a - request with a request with defined If-Modified-Since headers. - - .. versionadded:: 0.6 - The location can now be a unicode string that is encoded using - the :func:`iri_to_uri` function. - - .. versionadded:: 0.10 - The class used for the Response object can now be passed in. - - :param location: the location the response should redirect to. - :param code: the redirect status code. defaults to 302. - :param class Response: a Response class to use when instantiating a - response. The default is :class:`werkzeug.wrappers.Response` if - unspecified. - """ - if Response is None: - from .wrappers import Response - - display_location = escape(location) - if isinstance(location, text_type): - # Safe conversion is necessary here as we might redirect - # to a broken URI scheme (for instance itms-services). - from .urls import iri_to_uri - - location = iri_to_uri(location, safe_conversion=True) - response = Response( - '\n' - "Redirecting...\n" - "

    Redirecting...

    \n" - "

    You should be redirected automatically to target URL: " - '%s. If not click the link.' - % (escape(location), display_location), - code, - mimetype="text/html", - ) - response.headers["Location"] = location - return response - - -def append_slash_redirect(environ, code=301): - """Redirects to the same URL but with a slash appended. The behavior - of this function is undefined if the path ends with a slash already. - - :param environ: the WSGI environment for the request that triggers - the redirect. - :param code: the status code for the redirect. - """ - new_path = environ["PATH_INFO"].strip("/") + "/" - query_string = environ.get("QUERY_STRING") - if query_string: - new_path += "?" + query_string - return redirect(new_path, code) - - -def import_string(import_name, silent=False): - """Imports an object based on a string. This is useful if you want to - use import paths as endpoints or something similar. An import path can - be specified either in dotted notation (``xml.sax.saxutils.escape``) - or with a colon as object delimiter (``xml.sax.saxutils:escape``). - - If `silent` is True the return value will be `None` if the import fails. - - :param import_name: the dotted name for the object to import. - :param silent: if set to `True` import errors are ignored and - `None` is returned instead. - :return: imported object - """ - # force the import name to automatically convert to strings - # __import__ is not able to handle unicode strings in the fromlist - # if the module is a package - import_name = str(import_name).replace(":", ".") - try: - try: - __import__(import_name) - except ImportError: - if "." not in import_name: - raise - else: - return sys.modules[import_name] - - module_name, obj_name = import_name.rsplit(".", 1) - module = __import__(module_name, globals(), locals(), [obj_name]) - try: - return getattr(module, obj_name) - except AttributeError as e: - raise ImportError(e) - - except ImportError as e: - if not silent: - reraise( - ImportStringError, ImportStringError(import_name, e), sys.exc_info()[2] - ) - - -def find_modules(import_path, include_packages=False, recursive=False): - """Finds all the modules below a package. This can be useful to - automatically import all views / controllers so that their metaclasses / - function decorators have a chance to register themselves on the - application. - - Packages are not returned unless `include_packages` is `True`. This can - also recursively list modules but in that case it will import all the - packages to get the correct load path of that module. - - :param import_path: the dotted name for the package to find child modules. - :param include_packages: set to `True` if packages should be returned, too. - :param recursive: set to `True` if recursion should happen. - :return: generator - """ - module = import_string(import_path) - path = getattr(module, "__path__", None) - if path is None: - raise ValueError("%r is not a package" % import_path) - basename = module.__name__ + "." - for _importer, modname, ispkg in pkgutil.iter_modules(path): - modname = basename + modname - if ispkg: - if include_packages: - yield modname - if recursive: - for item in find_modules(modname, include_packages, True): - yield item - else: - yield modname - - -def validate_arguments(func, args, kwargs, drop_extra=True): - """Checks if the function accepts the arguments and keyword arguments. - Returns a new ``(args, kwargs)`` tuple that can safely be passed to - the function without causing a `TypeError` because the function signature - is incompatible. If `drop_extra` is set to `True` (which is the default) - any extra positional or keyword arguments are dropped automatically. - - The exception raised provides three attributes: - - `missing` - A set of argument names that the function expected but where - missing. - - `extra` - A dict of keyword arguments that the function can not handle but - where provided. - - `extra_positional` - A list of values that where given by positional argument but the - function cannot accept. - - This can be useful for decorators that forward user submitted data to - a view function:: - - from werkzeug.utils import ArgumentValidationError, validate_arguments - - def sanitize(f): - def proxy(request): - data = request.values.to_dict() - try: - args, kwargs = validate_arguments(f, (request,), data) - except ArgumentValidationError: - raise BadRequest('The browser failed to transmit all ' - 'the data expected.') - return f(*args, **kwargs) - return proxy - - :param func: the function the validation is performed against. - :param args: a tuple of positional arguments. - :param kwargs: a dict of keyword arguments. - :param drop_extra: set to `False` if you don't want extra arguments - to be silently dropped. - :return: tuple in the form ``(args, kwargs)``. - """ - parser = _parse_signature(func) - args, kwargs, missing, extra, extra_positional = parser(args, kwargs)[:5] - if missing: - raise ArgumentValidationError(tuple(missing)) - elif (extra or extra_positional) and not drop_extra: - raise ArgumentValidationError(None, extra, extra_positional) - return tuple(args), kwargs - - -def bind_arguments(func, args, kwargs): - """Bind the arguments provided into a dict. When passed a function, - a tuple of arguments and a dict of keyword arguments `bind_arguments` - returns a dict of names as the function would see it. This can be useful - to implement a cache decorator that uses the function arguments to build - the cache key based on the values of the arguments. - - :param func: the function the arguments should be bound for. - :param args: tuple of positional arguments. - :param kwargs: a dict of keyword arguments. - :return: a :class:`dict` of bound keyword arguments. - """ - ( - args, - kwargs, - missing, - extra, - extra_positional, - arg_spec, - vararg_var, - kwarg_var, - ) = _parse_signature(func)(args, kwargs) - values = {} - for (name, _has_default, _default), value in zip(arg_spec, args): - values[name] = value - if vararg_var is not None: - values[vararg_var] = tuple(extra_positional) - elif extra_positional: - raise TypeError("too many positional arguments") - if kwarg_var is not None: - multikw = set(extra) & set([x[0] for x in arg_spec]) - if multikw: - raise TypeError( - "got multiple values for keyword argument " + repr(next(iter(multikw))) - ) - values[kwarg_var] = extra - elif extra: - raise TypeError("got unexpected keyword argument " + repr(next(iter(extra)))) - return values - - -class ArgumentValidationError(ValueError): - - """Raised if :func:`validate_arguments` fails to validate""" - - def __init__(self, missing=None, extra=None, extra_positional=None): - self.missing = set(missing or ()) - self.extra = extra or {} - self.extra_positional = extra_positional or [] - ValueError.__init__( - self, - "function arguments invalid. (%d missing, %d additional)" - % (len(self.missing), len(self.extra) + len(self.extra_positional)), - ) - - -class ImportStringError(ImportError): - """Provides information about a failed :func:`import_string` attempt.""" - - #: String in dotted notation that failed to be imported. - import_name = None - #: Wrapped exception. - exception = None - - def __init__(self, import_name, exception): - self.import_name = import_name - self.exception = exception - - msg = ( - "import_string() failed for %r. Possible reasons are:\n\n" - "- missing __init__.py in a package;\n" - "- package or module path not included in sys.path;\n" - "- duplicated package or module name taking precedence in " - "sys.path;\n" - "- missing module, class, function or variable;\n\n" - "Debugged import:\n\n%s\n\n" - "Original exception:\n\n%s: %s" - ) - - name = "" - tracked = [] - for part in import_name.replace(":", ".").split("."): - name += (name and ".") + part - imported = import_string(name, silent=True) - if imported: - tracked.append((name, getattr(imported, "__file__", None))) - else: - track = ["- %r found in %r." % (n, i) for n, i in tracked] - track.append("- %r not found." % name) - msg = msg % ( - import_name, - "\n".join(track), - exception.__class__.__name__, - str(exception), - ) - break - - ImportError.__init__(self, msg) - - def __repr__(self): - return "<%s(%r, %r)>" % ( - self.__class__.__name__, - self.import_name, - self.exception, - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__init__.py deleted file mode 100644 index 56c764a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -werkzeug.wrappers -~~~~~~~~~~~~~~~~~ - -The wrappers are simple request and response objects which you can -subclass to do whatever you want them to do. The request object contains -the information transmitted by the client (webbrowser) and the response -object contains all the information sent back to the browser. - -An important detail is that the request object is created with the WSGI -environ and will act as high-level proxy whereas the response object is an -actual WSGI application. - -Like everything else in Werkzeug these objects will work correctly with -unicode data. Incoming form data parsed by the response object will be -decoded into an unicode object if possible and if it makes sense. - -:copyright: 2007 Pallets -:license: BSD-3-Clause -""" -from .accept import AcceptMixin -from .auth import AuthorizationMixin -from .auth import WWWAuthenticateMixin -from .base_request import BaseRequest -from .base_response import BaseResponse -from .common_descriptors import CommonRequestDescriptorsMixin -from .common_descriptors import CommonResponseDescriptorsMixin -from .etag import ETagRequestMixin -from .etag import ETagResponseMixin -from .request import PlainRequest -from .request import Request -from .request import StreamOnlyMixin -from .response import Response -from .response import ResponseStream -from .response import ResponseStreamMixin -from .user_agent import UserAgentMixin diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index ccd57ca5545d6e9ccb8f587aee2a69af56e0dafa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1636 zcmaJ>&2Aev5SDD&l2?D0>?C!87IUl*vVyii03!%$Cq)pTKS7*A01sVIyNs3NmH zigM_C^bz_dc?Ml`Y9FDe47nnd8bwzS@o{GOapoJ6*ZqFdz|S`S__a7_G(PxA{Pqxh zhkyGXhrB@=c{AS=O}R(*njY_qec2+dfLn+U$U(pd;!w6pJK#gnkw@ex;I>F)mvjT} zAnuV~z(=Al2V@X%f_O-V0e8i*9FbALJ;Y-&4!Do_gq#FC5U27ExfAdZ@m+E^;A6!1 z$i09^;xlQ|1(6VI4CcoeQlH_HTaO$}-UN-&p1>tO}kLu+|l1R3)~WXM$P_PD8HINgaE`Oz^L$a^MOkYv%=k z-!PKbe2{77C|5SYK;Y_?Hj+B76*xncmE1X&!+h;|AQPM+cWnzr(JGt=N8J)EHM*RDh=i zY^LB@PzaO#fiD?&z1ObbY5`1Oqqu_Ew)>v+)7JSsR@y94bz`ub0=LJklS=VS=L~Y{ zD7NXD%Cz)+z8k>^B{g=}h$wcj9yc?Y)Ni^!tAdrd8SQJ;ET+^eVc!N>U*kF}Iq zZ3CV#n;Bj@ZERfsWelj7{71y`_b=&UOAuF$YFoV~8hg(LUWZ*S?HwH6I6NuxXC>A# zy7OXtJu%Bc#B~^2PX29)iw3{o&AD2j2*L8x`RAKTjSclzOs)zPs1Vt28aSYh1k+_#Vl%|)ocH@1S4= zHKJ{XxWL{amVYJ#*snWwDZoO z9oD_Ky&mnpHio^wEKoZ%i`_{;xL|VZ`z(_%v3Ej}c~0i6ndzS%pH7?6<4oYuHTE?}CH8r@E4(TonloXxR;5SnO9m z*Cu}glS0M7a4d8AWD7d=&h6klf|Kj1c5muL`>lqCC4Nf7WWI?_X@qbQnl|geL{gGR zG9K&fRw+a{Lw*`(Ko1e730f%>xer_wXub?H(DXvlxDG@>ZW*YH()1eG+9<1Ny@|oa zTE2d~j_-6f`R?1}+0oF}iMs-LXl})}PQ1p%&lI>i@!DGxui3aA+yA05QEaaPj;gY| z72ppd@@4^FC0~P{>!Mqr8bkqbPUeiFFWs-3RfyGbf*?+}VVaA2XJys`;zST<^E@Ja z{m6smrOe2cH7X}m^EN_tGM*iMKR%jPHD(nmZbJ+nh*tyQ=PF*B3_T#jwo=h-oeg_M z7vqG)4CA7Yah%dTQt|-fo18?|N(W<_`WSO~rwzWVx;@pYn#2`()(EOBC_-#sv^pZyOU(n(YR diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/auth.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/auth.cpython-37.pyc deleted file mode 100644 index 6d279cee157b216552200837ee5b9c0b618a72cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1652 zcmbW1&u`l{6vs(Pww26o)3g|hq635hJGg-5%MOE)2F-eCdRSU)9s=kvniH8?jV!4o zRkwn>OM-3x!fxwvhy6pk?$m#wr@cp2o}KkDi~=9{OYeOj`60g^40Z_=O@I60XOED- zu+tXklLt`sF&IGvP04~rlw#X~wi7wF?WXR+i#$pm5#fo>B@rFjxp1Q{^t+-5{hsaj zg#R5G?!0rr-H_II3a+$dyfpJ%B^5VGp0T;)LMoX3teIUdmv)8BOcHY=|5$b#QWvruruwNYhkN^l=u`8)sdxr|L{|BWeRi3N8SQ-26m-vYBD&&lsp z(6{srHO`7&P)OOS?oC1GRXvTzAjv*t5S-;|5k~vR)9F)o^!@bs$+wTAqv_)(CquXH z$?RpK@~n2BNu%tEI<==|dRBLv#Qq=((Rx1_n?*4$l44Y51&`0A7%k^grlS{Z{$&Cq z<2K{*Qt<-LQjc-F!{T*4*xL6#W`$4^w@<5JYeVd@gE7#D#<&j4QC0x zMt7-4tFJzG1Yzr|)e#<~dCXIN7_MFYTkOzP``}si(BMwMfK`G!qIS^WWoY$TX_)cW z+x97}(1;lE`duLWi~pn#FjoWkM_og69nBt?+HW5zg%807%_u}!q;EjW9vPDFQ$QL= wPKJK%&5bGSwYJ&Rozf(!wl}2iHn3Uz?GGRGUHb>kbvr~h?7sIYeD2=hZ{07q5C8xG diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_request.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_request.cpython-37.pyc deleted file mode 100644 index cfc07c288d6fbfa885044db9331b48a1afbcf79b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21462 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 Ne_{GJx%7YR{{p6+;h_Kk diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_response.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/base_response.cpython-37.pyc deleted file mode 100644 index b582a32ff26efa03a8e83e4f4c6a29be39a48487..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23136 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 Fe*yPot-1gJ diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/common_descriptors.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/common_descriptors.cpython-37.pyc deleted file mode 100644 index b1e6b20d6e10cb4445c61fde7932136960b074ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12725 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/cors.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/cors.cpython-37.pyc deleted file mode 100644 index 258c03688695eb4cf9e7ec0a15fcb2ecace14120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3248 zcmc&$OOG2x5T1u0W3TrWP%cSO3nYS(>;)77T18PD$I1q=Yp{(X&4Eepbnnh&=augE zdUq6YNlr-l0Z1I+$OZleKLBxFHClnsy#+fcF@m|@8-DY*o4*)HqaJ&lw} z<(Wn*wDQ!ntI)3!3;LGoTckGBn)N>oFx}L%6*3MJ$D^1~2HlMWGfo{&#hGt3I`&x{ zISGps%ET%Bx1MXvKDl6Rc9lW84G;eq8miek(QJe0wnQhg3i zLJu5MBNnNHgDcraw?7yT=;JZvV%IejI^SO18JrhwTs4h`q8i8hzpP2lwyY-%GzAc@%ju z7r6@pdMsZYiq)K0P=XFv9JbMr3bc)dV6ePA3OtD;PE{D%*mWuAjvGgU#esu^Af7n6 zjfW_Xz`it{YakILKO(*h*3rcCU9XspBg`mLx|FnGM@a{zQAE9aUhZM*8am z4~l{^zyeAD9DE#bAmvYa2zsJluPwB=hCuG*A$L3pAQ{m5c( z5<_kdF>h+onv{Offwi?C)u976th6`EN`j5)D=gPwn_xIIlQ?M_?2?qr$2b_%xmB|_ zVCWV+To#{ZSbD=quP%+|jykOH^wS55&!$*D&6k&xOVeZ)%wgBm*=Gj#7fiRS@S3Ne z+x{AIc{j@g%3M|MENZ|VW*A*Gy=ydv3omfJAib8y}oGm%tU?6Ly#I*0LNT4v YTINt@-OOqJmPBiX(hXhR=En8E0q+IgEC2ui diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/etag.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/etag.cpython-37.pyc deleted file mode 100644 index 715e65b448e2387346718cbd4eb1c6e0bb3c8953..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11518 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 ZD&J9WH+)K#80P!29?sdM3LocXK1dp z+@)uRmc>#z#J&~Dy+9Aru|TiA<T0_=ljM{c;cWv|UbRF(+H+6@VZUu7= zucXysty?qgYU&N^-8!>Q8fLZMUHin!wp>dzj(j;_7X8f3dUx&jR%So2-m`d(d(SNH ziH)aD_X_%T?xXLU{wBBgtmfL+kjZMY;!1R&@^q|4m<&g`)Sa*Ga-y!q6CLW4k-#ed z?TG(YJQ@q7(R+mpEn*#xbw3nYobx1m7}I|9$3f!`ih2{3u)2&}U0XPuar>F|lyzNE zA)QUTit!4sns$xXAe&dLg&*wwrt@LW$Ek=J_MnIUY2&*n>U~t&np&D2+D~nHeQKRK z=hj|1<{nlsc2ifUI1FR8DZt0bZS7%Q{k$CYpIVQaMLkh@KbONu7w&kR@WTE0f@)Zm}Z|~~iXm^y1cE;H#ijM@}IUWd+?mP+yZzUMnJr?q4BE}DQk7YC( z38{7uRi3p*Cyglt*9%Q zQg|dz)PB>YrFu3azl9@6;(XoN3tgd6R{0^$`q9{U? zblqSLHo3a0rP*g;D5N44qv97D`sBUF8B+F65S(Nb`u3)J(~M2E4fsT$cO?nEesTOmg4$m~UT{-0anX$-@A% zXeh$4@WXIuEFbMg7(N1?I}qtr<}6nc>J63MkVjg*>=5K@v3T@i%rO&T0)Xn~?E zMJjo$vEHaj8jDdD58-wPMRickJ(shtBiwF9RJqNa(o@lfX_&UhtGxEi>ehuX{Jz~? z<5#%P*PgL%gE#m(X4d%zjApZ_8@EoLBw6$h-1$Rl1v(F4NJ<24a-Mb%eirqDNCmXG z72J)o;6Mb! zX-$%6hLn2SffBeqGQxH*QO37>&6$Gq_Fdqm<_jJQU9Jd@6FmrKybwh4;dm%A4e03= zdO(@pd^Osx5@~(Yi+(=blxjF5*cA*;yZ|SE2gfm~~oZ z*5v)EEhijv*#9rI{~zqr+Nn3KO)GswqR`4-13a~9mEK=jO`;ORz7+;o0haj&IM|_VA4E?&u2L(ZN>oqHvw$pfJ80) zK?*&VnF@NnPM(QgZ-pNq3q=5AkwHI7Qnfwjiaaw{98#3TY)G?$gQZjummEANcTy?Q zDkx709!Kd|(6X@tF(a0cuB&q^r?)AM8B$z{MLW3vFw3R5hz$-2qVzaA!9Mb28L&)% zS|~W%M?u6)w}U1 zT4FMc!v7sXY*O3e)feAW(=Q39Vxa9-OJvNUCYz25TRtwB=+*)GFiJz}h246&4!uj> zFSjAerzq+sDr@r^vMHarcEh&WCVnp3E=a3k`{sX(YI|~RNeA<2a)HB$4h#icLqo&O z&JY#O*;9tE1Nu~QCf`s1qkxZqSw^|}M!k!MYi>7D*$o{SC1SC1k;da-lC(oUHv$+$ zX{_6`bmCQcJd~P*g<`3R(SeK-C6<2J7Ej{Ugb7_SqF}CC%a1&G zCmAC>lkeX%UPoqMrom+jfovV$fbHOqZ=QBQ*%g3SR3RKbjphvgD~w&f!(U+RPbg)) zu1?HmCJ}7C*orz$=ia^j=7xNocDq3pU4KyvL!?AuXmVKja~kqSGRL=)K9Mb2wlH7$ zGwS}7Dl#ESGOWn8Op)Kf#4d`WJlU(eE{v<*Xn1wc_ID)BHm_2C-XDX@kgH3Ifs$f~ zTt@|&;(R!YwD|%o{3Wy{Je9EqyO~dluD{Ii%Fl|m`{w)Gc$AU9sFo0y3ew>(lDY7H dStgXXDFIZkqG}*?)At~L@C^E1+Hf|%_ixKrZ>#_S diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/request.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/request.cpython-37.pyc deleted file mode 100644 index 24df2ae09e0dc13ca1f8f2370ff137eb9718b5fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1939 zcmah~&5q+l5Vm9IKbd3)A-Ev*4Mide2QEZ_c6MM92WHUBa4`~2$6bkgxBWBS?Flmn zF2ge*@d&(a$H7Orzy0`E-Esafi|u1}p5v>2 zMZz5B3MX*`*EM`i)Dkc7Ebj?FsRwn-`=XIFgQn%{qLs9Rw&fe5lXQcw<(s0H^n$UD`dyzvuX>Arf!`mpMU=xq-)O=)YGs zH@c{a`UEP^|9T?f$$5`T7Bh)nqMco`Y1A2&+0dtY)R~ z9Gy_syh+}rBOuo?l_tYg!m4xo3I0zARR$u9vYiHN>SE-VtuRb!0%2Ho z!Z68LAq?LO!`p(2%}z56Sr&!i?~Xh{{8;k$=Tn{J)12qyBF$;^8rXOp1Bmf$7=OZ1 zGTkO%x=p}zgQZD+FWacd^tP%YX}x3D$07SZ9(WV7fzQ04&U}P!y&PO?2{gG(#l7tg z`XNI2o25Y`q8GEc0E8S^tR7%l$6S#$N3=%>pH+2c0WrPfnY0r1n~7@d}lYO+ZqE`2i~q=#(KTj0zOH}I3b5uH{YxtCid@#E(Nz8MqJ z!- diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/response.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/response.cpython-37.pyc deleted file mode 100644 index dcffc323135ab2b69bf699ce7a54b517e8baba5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3468 zcma)9-EJF26y87E8^?CiG^L^xH2exv*%1=rBC4u1X$zGgMNLG|O0e1NjO|VLFEg`E zV;L?;#T^g8U3$q=@CH1vSIG^J?CLd4o1#-eeUv&rCMQTC8?#I}5b6 zrL`Ac8X!zt&lh~pA28~sJV_asM=$kaeR*eR=WZqkES7=qN%nQ{EQo==vF-`>n29ur z1%vrJ8%Y!;ak+Aj37-e4Ot>g_T-kW^c&q$AS-ijP^`{nnICoM^7_C7S-$BDPN2i)& zP~9=9;aJq9)^p9N&Uy@8PO7@NjsD-Thp(n)Z?lcE= zzg;4eI)TDj%9#KasvUa?Jt9d@jfFa|OUOe>XuyGactp}n445E6EE7cpdzG3MuRt>H z?SX7#4&}$OY+Xe(G!OS~`Dj`!*kj#*Di)y`=_Abr0745I1q~RR586gMgxaW_56ZPyLrK)UV~6vu)_)2sUM`s48}3lnrps;OHbwYtSR3`W|%##>US`mz2q z+-2X`2V79|S8ypcGfu3L{-T^!PO8+R+6zP1WNid{;NF$Z;mwCDj|gJklR**__$%(N z0I=QGom!MhRQRy9k;D>=*!haZeK}~`d>*98>)(1|#_n^TaHXew(Pgp7ICBL%$XM*N zyozdwXoteY@-_QpuRr+wf0(HLnb+Q>k)98`DU9RfAzn{Az62dcJNh+~52xdmrO z=S8ZkbHX5I;%(S4wqIQzzIl;6iq6NU1Pk^P93rF?0t*q0P0+PcD0Fz)^9NUyS>A;& z0(oe&8c+lmAGQP=rr|P%{j1Fn)V@E~9{|BAl+T++k^FDL3^0iK8eD?6 zzE-koAUr9LK1R{1&=lwyUOQ)}f@(^-Dd3>mPV^UGJZVT%S~%a=jt%8M0Gx^fJx6EG zO_4>p8F?v3%wD1~OR_NR!1q(^Ts z7bY}_`=8>m3O>fngHzIMwp;i{#a_f*H?O;Hl+Y~1al>^FGA|r|sktsqd|0-Cfbj)j zt$c{zz|mXSpyP3L6HcJX?J~IX_izng(=!cvJjWaXt5}A{wk*RkY|FNxnoujYr6_#( zI4S7rYfuHAb~Z*b3tvMO=PJ~~*DgP&XceV~f2xl35uU zr4$@t_B4R7tGIbYy*8aBhRqNT8Si;MgQz+c7D*Wri`X{>9JKWWI1->!z;<|R8$vf9 zN1O=*;)$~-j)OCR3QckewyFiyZM1+wmN~pJ4QHj^Zb7!$uJZSRl;exRKg8xEY;Y(4 z1e=Rc(S{G7LscGwsNlHbL!A`#kTs|(zMn+_Rqsh|moj<(0O^AaY|~?&gfK-<^)OCv zf+!7Hgc)DlSDNl6VVE4^Oqo`!)|GiWklK{#&rBY-s{qBM*C$>~iI3?e@gaipBqRe^ zg4ocXVRKQoS#bJtd;1%NQ<;fkuohXGCS1;N`Kio6x@88^^&u1O&Sank>kXcW0&s94 z@`wk0fG_AP$vB{G3!WCd`Z#va99AlJOQmwk*qHbckJ3^=r3y?IcT3doDmHjr3I7?s zuTH27$)AE~NhSy?XTtF`X)P|b*|sjk+(k&c1rSy%eD$Azdqxb7@yD^y2D}Et+(KM%e9ZG|0XpSk3fAh(i`*c$ aZx>JT9R$02?i%{!XD)UY8+F~7{Qd(zo^E{r diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/user_agent.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/__pycache__/user_agent.cpython-37.pyc deleted file mode 100644 index 84881b3952417905061d1c6387b8889d3c6974a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 794 zcmYjPy>in)5WbV-pBM*9h8c=$J%jCrD#I`i6se#A8Wo(+x{akomgKurOgtGH=OuUq zYF>e-P)o%tP_cW89q-JZcK24_e!F|`PEQ96#qu9te{shCkh7NvjTx$ag@U*Z8Q=9|Wb{xSY1n)FY52zoqZ&|VZeXg|?O3Z7lCKZ*N z3+0^27PSN6O5suv2G%uLC(6YYBu;G7EJ+6fB`FK1vcmeTN*N1U5R&jnqP+AM3sY_= z=u+hbLNAwKFcFbG$R1r0k+URM)}GD3Z@^q{pe8sB?V zOWSemj$QE`$KLt&`Dbh;sg1!Vk62DdfuWz89uzm3DGQu;WFf!&$xIL9|7KISs-{&| zjq9RP$u;QlCI!gHYni^zFf!e9oo|IU-M3FZg7g PuWdA+5` for more - details about customizing the behavior. - - Per default the request object will be added to the WSGI - environment as `werkzeug.request` to support the debugging system. - If you don't want that, set `populate_request` to `False`. - - If `shallow` is `True` the environment is initialized as shallow - object around the environ. Every operation that would modify the - environ in any way (such as consuming form data) raises an exception - unless the `shallow` attribute is explicitly set to `False`. This - is useful for middlewares where you don't want to consume the form - data by accident. A shallow request is not populated to the WSGI - environment. - - .. versionchanged:: 0.5 - read-only mode was enforced by using immutables classes for all - data. - """ - - #: the charset for the request, defaults to utf-8 - charset = "utf-8" - - #: the error handling procedure for errors, defaults to 'replace' - encoding_errors = "replace" - - #: the maximum content length. This is forwarded to the form data - #: parsing function (:func:`parse_form_data`). When set and the - #: :attr:`form` or :attr:`files` attribute is accessed and the - #: parsing fails because more than the specified value is transmitted - #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. - #: - #: Have a look at :ref:`dealing-with-request-data` for more details. - #: - #: .. versionadded:: 0.5 - max_content_length = None - - #: the maximum form field size. This is forwarded to the form data - #: parsing function (:func:`parse_form_data`). When set and the - #: :attr:`form` or :attr:`files` attribute is accessed and the - #: data in memory for post data is longer than the specified value a - #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. - #: - #: Have a look at :ref:`dealing-with-request-data` for more details. - #: - #: .. versionadded:: 0.5 - max_form_memory_size = None - - #: the class to use for `args` and `form`. The default is an - #: :class:`~werkzeug.datastructures.ImmutableMultiDict` which supports - #: multiple values per key. alternatively it makes sense to use an - #: :class:`~werkzeug.datastructures.ImmutableOrderedMultiDict` which - #: preserves order or a :class:`~werkzeug.datastructures.ImmutableDict` - #: which is the fastest but only remembers the last key. It is also - #: possible to use mutable structures, but this is not recommended. - #: - #: .. versionadded:: 0.6 - parameter_storage_class = ImmutableMultiDict - - #: the type to be used for list values from the incoming WSGI environment. - #: By default an :class:`~werkzeug.datastructures.ImmutableList` is used - #: (for example for :attr:`access_list`). - #: - #: .. versionadded:: 0.6 - list_storage_class = ImmutableList - - #: The type to be used for dict values from the incoming WSGI - #: environment. (For example for :attr:`cookies`.) By default an - #: :class:`~werkzeug.datastructures.ImmutableMultiDict` is used. - #: - #: .. versionchanged:: 1.0.0 - #: Changed to ``ImmutableMultiDict`` to support multiple values. - #: - #: .. versionadded:: 0.6 - dict_storage_class = ImmutableMultiDict - - #: The form data parser that shoud be used. Can be replaced to customize - #: the form date parsing. - form_data_parser_class = FormDataParser - - #: Optionally a list of hosts that is trusted by this request. By default - #: all hosts are trusted which means that whatever the client sends the - #: host is will be accepted. - #: - #: Because `Host` and `X-Forwarded-Host` headers can be set to any value by - #: a malicious client, it is recommended to either set this property or - #: implement similar validation in the proxy (if application is being run - #: behind one). - #: - #: .. versionadded:: 0.9 - trusted_hosts = None - - #: Indicates whether the data descriptor should be allowed to read and - #: buffer up the input stream. By default it's enabled. - #: - #: .. versionadded:: 0.9 - disable_data_descriptor = False - - def __init__(self, environ, populate_request=True, shallow=False): - self.environ = environ - if populate_request and not shallow: - self.environ["werkzeug.request"] = self - self.shallow = shallow - - def __repr__(self): - # make sure the __repr__ even works if the request was created - # from an invalid WSGI environment. If we display the request - # in a debug session we don't want the repr to blow up. - args = [] - try: - args.append("'%s'" % to_native(self.url, self.url_charset)) - args.append("[%s]" % self.method) - except Exception: - args.append("(invalid WSGI environ)") - - return "<%s %s>" % (self.__class__.__name__, " ".join(args)) - - @property - def url_charset(self): - """The charset that is assumed for URLs. Defaults to the value - of :attr:`charset`. - - .. versionadded:: 0.6 - """ - return self.charset - - @classmethod - def from_values(cls, *args, **kwargs): - """Create a new request object based on the values provided. If - environ is given missing values are filled from there. This method is - useful for small scripts when you need to simulate a request from an URL. - Do not use this method for unittesting, there is a full featured client - object (:class:`Client`) that allows to create multipart requests, - support for cookies etc. - - This accepts the same options as the - :class:`~werkzeug.test.EnvironBuilder`. - - .. versionchanged:: 0.5 - This method now accepts the same arguments as - :class:`~werkzeug.test.EnvironBuilder`. Because of this the - `environ` parameter is now called `environ_overrides`. - - :return: request object - """ - from ..test import EnvironBuilder - - charset = kwargs.pop("charset", cls.charset) - kwargs["charset"] = charset - builder = EnvironBuilder(*args, **kwargs) - try: - return builder.get_request(cls) - finally: - builder.close() - - @classmethod - def application(cls, f): - """Decorate a function as responder that accepts the request as - the last argument. This works like the :func:`responder` - decorator but the function is passed the request object as the - last argument and the request object will be closed - automatically:: - - @Request.application - def my_wsgi_app(request): - return Response('Hello World!') - - As of Werkzeug 0.14 HTTP exceptions are automatically caught and - converted to responses instead of failing. - - :param f: the WSGI callable to decorate - :return: a new WSGI callable - """ - #: return a callable that wraps the -2nd argument with the request - #: and calls the function with all the arguments up to that one and - #: the request. The return value is then called with the latest - #: two arguments. This makes it possible to use this decorator for - #: both standalone WSGI functions as well as bound methods and - #: partially applied functions. - from ..exceptions import HTTPException - - def application(*args): - request = cls(args[-2]) - with request: - try: - resp = f(*args[:-2] + (request,)) - except HTTPException as e: - resp = e.get_response(args[-2]) - return resp(*args[-2:]) - - return update_wrapper(application, f) - - def _get_file_stream( - self, total_content_length, content_type, filename=None, content_length=None - ): - """Called to get a stream for the file upload. - - This must provide a file-like class with `read()`, `readline()` - and `seek()` methods that is both writeable and readable. - - The default implementation returns a temporary file if the total - content length is higher than 500KB. Because many browsers do not - provide a content length for the files only the total content - length matters. - - :param total_content_length: the total content length of all the - data in the request combined. This value - is guaranteed to be there. - :param content_type: the mimetype of the uploaded file. - :param filename: the filename of the uploaded file. May be `None`. - :param content_length: the length of this file. This value is usually - not provided because webbrowsers do not provide - this value. - """ - return default_stream_factory( - total_content_length=total_content_length, - filename=filename, - content_type=content_type, - content_length=content_length, - ) - - @property - def want_form_data_parsed(self): - """Returns True if the request method carries content. As of - Werkzeug 0.9 this will be the case if a content type is transmitted. - - .. versionadded:: 0.8 - """ - return bool(self.environ.get("CONTENT_TYPE")) - - def make_form_data_parser(self): - """Creates the form data parser. Instantiates the - :attr:`form_data_parser_class` with some parameters. - - .. versionadded:: 0.8 - """ - return self.form_data_parser_class( - self._get_file_stream, - self.charset, - self.encoding_errors, - self.max_form_memory_size, - self.max_content_length, - self.parameter_storage_class, - ) - - def _load_form_data(self): - """Method used internally to retrieve submitted data. After calling - this sets `form` and `files` on the request object to multi dicts - filled with the incoming form data. As a matter of fact the input - stream will be empty afterwards. You can also call this method to - force the parsing of the form data. - - .. versionadded:: 0.8 - """ - # abort early if we have already consumed the stream - if "form" in self.__dict__: - return - - _assert_not_shallow(self) - - if self.want_form_data_parsed: - content_type = self.environ.get("CONTENT_TYPE", "") - content_length = get_content_length(self.environ) - mimetype, options = parse_options_header(content_type) - parser = self.make_form_data_parser() - data = parser.parse( - self._get_stream_for_parsing(), mimetype, content_length, options - ) - else: - data = ( - self.stream, - self.parameter_storage_class(), - self.parameter_storage_class(), - ) - - # inject the values into the instance dict so that we bypass - # our cached_property non-data descriptor. - d = self.__dict__ - d["stream"], d["form"], d["files"] = data - - def _get_stream_for_parsing(self): - """This is the same as accessing :attr:`stream` with the difference - that if it finds cached data from calling :meth:`get_data` first it - will create a new stream out of the cached data. - - .. versionadded:: 0.9.3 - """ - cached_data = getattr(self, "_cached_data", None) - if cached_data is not None: - return BytesIO(cached_data) - return self.stream - - def close(self): - """Closes associated resources of this request object. This - closes all file handles explicitly. You can also use the request - object in a with statement which will automatically close it. - - .. versionadded:: 0.9 - """ - files = self.__dict__.get("files") - for _key, value in iter_multi_items(files or ()): - value.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close() - - @cached_property - def stream(self): - """ - If the incoming form data was not encoded with a known mimetype - the data is stored unmodified in this stream for consumption. Most - of the time it is a better idea to use :attr:`data` which will give - you that data as a string. The stream only returns the data once. - - Unlike :attr:`input_stream` this stream is properly guarded that you - can't accidentally read past the length of the input. Werkzeug will - internally always refer to this stream to read data which makes it - possible to wrap this object with a stream that does filtering. - - .. versionchanged:: 0.9 - This stream is now always available but might be consumed by the - form parser later on. Previously the stream was only set if no - parsing happened. - """ - _assert_not_shallow(self) - return get_input_stream(self.environ) - - input_stream = environ_property( - "wsgi.input", - """The WSGI input stream. - - In general it's a bad idea to use this one because you can - easily read past the boundary. Use the :attr:`stream` - instead.""", - ) - - @cached_property - def args(self): - """The parsed URL parameters (the part in the URL after the question - mark). - - By default an - :class:`~werkzeug.datastructures.ImmutableMultiDict` - is returned from this function. This can be changed by setting - :attr:`parameter_storage_class` to a different type. This might - be necessary if the order of the form data is important. - """ - return url_decode( - wsgi_get_bytes(self.environ.get("QUERY_STRING", "")), - self.url_charset, - errors=self.encoding_errors, - cls=self.parameter_storage_class, - ) - - @cached_property - def data(self): - """ - Contains the incoming request data as string in case it came with - a mimetype Werkzeug does not handle. - """ - - if self.disable_data_descriptor: - raise AttributeError("data descriptor is disabled") - # XXX: this should eventually be deprecated. - - # We trigger form data parsing first which means that the descriptor - # will not cache the data that would otherwise be .form or .files - # data. This restores the behavior that was there in Werkzeug - # before 0.9. New code should use :meth:`get_data` explicitly as - # this will make behavior explicit. - return self.get_data(parse_form_data=True) - - def get_data(self, cache=True, as_text=False, parse_form_data=False): - """This reads the buffered incoming data from the client into one - bytestring. By default this is cached but that behavior can be - changed by setting `cache` to `False`. - - Usually it's a bad idea to call this method without checking the - content length first as a client could send dozens of megabytes or more - to cause memory problems on the server. - - Note that if the form data was already parsed this method will not - return anything as form data parsing does not cache the data like - this method does. To implicitly invoke form data parsing function - set `parse_form_data` to `True`. When this is done the return value - of this method will be an empty string if the form parser handles - the data. This generally is not necessary as if the whole data is - cached (which is the default) the form parser will used the cached - data to parse the form data. Please be generally aware of checking - the content length first in any case before calling this method - to avoid exhausting server memory. - - If `as_text` is set to `True` the return value will be a decoded - unicode string. - - .. versionadded:: 0.9 - """ - rv = getattr(self, "_cached_data", None) - if rv is None: - if parse_form_data: - self._load_form_data() - rv = self.stream.read() - if cache: - self._cached_data = rv - if as_text: - rv = rv.decode(self.charset, self.encoding_errors) - return rv - - @cached_property - def form(self): - """The form parameters. By default an - :class:`~werkzeug.datastructures.ImmutableMultiDict` - is returned from this function. This can be changed by setting - :attr:`parameter_storage_class` to a different type. This might - be necessary if the order of the form data is important. - - Please keep in mind that file uploads will not end up here, but instead - in the :attr:`files` attribute. - - .. versionchanged:: 0.9 - - Previous to Werkzeug 0.9 this would only contain form data for POST - and PUT requests. - """ - self._load_form_data() - return self.form - - @cached_property - def values(self): - """A :class:`werkzeug.datastructures.CombinedMultiDict` that combines - :attr:`args` and :attr:`form`.""" - args = [] - for d in self.args, self.form: - if not isinstance(d, MultiDict): - d = MultiDict(d) - args.append(d) - return CombinedMultiDict(args) - - @cached_property - def files(self): - """:class:`~werkzeug.datastructures.MultiDict` object containing - all uploaded files. Each key in :attr:`files` is the name from the - ````. Each value in :attr:`files` is a - Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. - - It basically behaves like a standard file object you know from Python, - with the difference that it also has a - :meth:`~werkzeug.datastructures.FileStorage.save` function that can - store the file on the filesystem. - - Note that :attr:`files` will only contain data if the request method was - POST, PUT or PATCH and the ``

    `` that posted to the request had - ``enctype="multipart/form-data"``. It will be empty otherwise. - - See the :class:`~werkzeug.datastructures.MultiDict` / - :class:`~werkzeug.datastructures.FileStorage` documentation for - more details about the used data structure. - """ - self._load_form_data() - return self.files - - @cached_property - def cookies(self): - """A :class:`dict` with the contents of all cookies transmitted with - the request.""" - return parse_cookie( - self.environ, - self.charset, - self.encoding_errors, - cls=self.dict_storage_class, - ) - - @cached_property - def headers(self): - """The headers from the WSGI environ as immutable - :class:`~werkzeug.datastructures.EnvironHeaders`. - """ - return EnvironHeaders(self.environ) - - @cached_property - def path(self): - """Requested path as unicode. This works a bit like the regular path - info in the WSGI environment but will always include a leading slash, - even if the URL root is accessed. - """ - raw_path = wsgi_decoding_dance( - self.environ.get("PATH_INFO") or "", self.charset, self.encoding_errors - ) - return "/" + raw_path.lstrip("/") - - @cached_property - def full_path(self): - """Requested path as unicode, including the query string.""" - return self.path + u"?" + to_unicode(self.query_string, self.url_charset) - - @cached_property - def script_root(self): - """The root path of the script without the trailing slash.""" - raw_path = wsgi_decoding_dance( - self.environ.get("SCRIPT_NAME") or "", self.charset, self.encoding_errors - ) - return raw_path.rstrip("/") - - @cached_property - def url(self): - """The reconstructed current URL as IRI. - See also: :attr:`trusted_hosts`. - """ - return get_current_url(self.environ, trusted_hosts=self.trusted_hosts) - - @cached_property - def base_url(self): - """Like :attr:`url` but without the querystring - See also: :attr:`trusted_hosts`. - """ - return get_current_url( - self.environ, strip_querystring=True, trusted_hosts=self.trusted_hosts - ) - - @cached_property - def url_root(self): - """The full URL root (with hostname), this is the application - root as IRI. - See also: :attr:`trusted_hosts`. - """ - return get_current_url(self.environ, True, trusted_hosts=self.trusted_hosts) - - @cached_property - def host_url(self): - """Just the host with scheme as IRI. - See also: :attr:`trusted_hosts`. - """ - return get_current_url( - self.environ, host_only=True, trusted_hosts=self.trusted_hosts - ) - - @cached_property - def host(self): - """Just the host including the port if available. - See also: :attr:`trusted_hosts`. - """ - return get_host(self.environ, trusted_hosts=self.trusted_hosts) - - query_string = environ_property( - "QUERY_STRING", - "", - read_only=True, - load_func=wsgi_get_bytes, - doc="The URL parameters as raw bytestring.", - ) - method = environ_property( - "REQUEST_METHOD", - "GET", - read_only=True, - load_func=lambda x: x.upper(), - doc="The request method. (For example ``'GET'`` or ``'POST'``).", - ) - - @cached_property - def access_route(self): - """If a forwarded header exists this is a list of all ip addresses - from the client ip to the last proxy server. - """ - if "HTTP_X_FORWARDED_FOR" in self.environ: - return self.list_storage_class( - parse_list_header(self.environ["HTTP_X_FORWARDED_FOR"]) - ) - elif "REMOTE_ADDR" in self.environ: - return self.list_storage_class([self.environ["REMOTE_ADDR"]]) - return self.list_storage_class() - - @property - def remote_addr(self): - """The remote address of the client.""" - return self.environ.get("REMOTE_ADDR") - - remote_user = environ_property( - "REMOTE_USER", - doc="""If the server supports user authentication, and the - script is protected, this attribute contains the username the - user has authenticated as.""", - ) - scheme = environ_property( - "wsgi.url_scheme", - doc=""" - URL scheme (http or https). - - .. versionadded:: 0.7""", - ) - is_secure = property( - lambda self: self.environ["wsgi.url_scheme"] == "https", - doc="`True` if the request is secure.", - ) - is_multithread = environ_property( - "wsgi.multithread", - doc="""boolean that is `True` if the application is served by a - multithreaded WSGI server.""", - ) - is_multiprocess = environ_property( - "wsgi.multiprocess", - doc="""boolean that is `True` if the application is served by a - WSGI server that spawns multiple processes.""", - ) - is_run_once = environ_property( - "wsgi.run_once", - doc="""boolean that is `True` if the application will be - executed only once in a process lifetime. This is the case for - CGI for example, but it's not guaranteed that the execution only - happens one time.""", - ) - - -def _assert_not_shallow(request): - if request.shallow: - raise RuntimeError( - "A shallow request tried to consume form data. If you really" - " want to do that, set `shallow` to False." - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py deleted file mode 100644 index 00b9640..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py +++ /dev/null @@ -1,700 +0,0 @@ -import warnings - -from .._compat import integer_types -from .._compat import string_types -from .._compat import text_type -from .._compat import to_bytes -from .._compat import to_native -from ..datastructures import Headers -from ..http import dump_cookie -from ..http import HTTP_STATUS_CODES -from ..http import remove_entity_headers -from ..urls import iri_to_uri -from ..urls import url_join -from ..utils import get_content_type -from ..wsgi import ClosingIterator -from ..wsgi import get_current_url - - -def _run_wsgi_app(*args): - """This function replaces itself to ensure that the test module is not - imported unless required. DO NOT USE! - """ - global _run_wsgi_app - from ..test import run_wsgi_app as _run_wsgi_app - - return _run_wsgi_app(*args) - - -def _warn_if_string(iterable): - """Helper for the response objects to check if the iterable returned - to the WSGI server is not a string. - """ - if isinstance(iterable, string_types): - warnings.warn( - "Response iterable was set to a string. This will appear to" - " work but means that the server will send the data to the" - " client one character at a time. This is almost never" - " intended behavior, use 'response.data' to assign strings" - " to the response object.", - stacklevel=2, - ) - - -def _iter_encoded(iterable, charset): - for item in iterable: - if isinstance(item, text_type): - yield item.encode(charset) - else: - yield item - - -def _clean_accept_ranges(accept_ranges): - if accept_ranges is True: - return "bytes" - elif accept_ranges is False: - return "none" - elif isinstance(accept_ranges, text_type): - return to_native(accept_ranges) - raise ValueError("Invalid accept_ranges value") - - -class BaseResponse(object): - """Base response class. The most important fact about a response object - is that it's a regular WSGI application. It's initialized with a couple - of response parameters (headers, body, status code etc.) and will start a - valid WSGI response when called with the environ and start response - callable. - - Because it's a WSGI application itself processing usually ends before the - actual response is sent to the server. This helps debugging systems - because they can catch all the exceptions before responses are started. - - Here a small example WSGI application that takes advantage of the - response objects:: - - from werkzeug.wrappers import BaseResponse as Response - - def index(): - return Response('Index page') - - def application(environ, start_response): - path = environ.get('PATH_INFO') or '/' - if path == '/': - response = index() - else: - response = Response('Not Found', status=404) - return response(environ, start_response) - - Like :class:`BaseRequest` which object is lacking a lot of functionality - implemented in mixins. This gives you a better control about the actual - API of your response objects, so you can create subclasses and add custom - functionality. A full featured response object is available as - :class:`Response` which implements a couple of useful mixins. - - To enforce a new type of already existing responses you can use the - :meth:`force_type` method. This is useful if you're working with different - subclasses of response objects and you want to post process them with a - known interface. - - Per default the response object will assume all the text data is `utf-8` - encoded. Please refer to :doc:`the unicode chapter ` for more - details about customizing the behavior. - - Response can be any kind of iterable or string. If it's a string it's - considered being an iterable with one item which is the string passed. - Headers can be a list of tuples or a - :class:`~werkzeug.datastructures.Headers` object. - - Special note for `mimetype` and `content_type`: For most mime types - `mimetype` and `content_type` work the same, the difference affects - only 'text' mimetypes. If the mimetype passed with `mimetype` is a - mimetype starting with `text/`, the charset parameter of the response - object is appended to it. In contrast the `content_type` parameter is - always added as header unmodified. - - .. versionchanged:: 0.5 - the `direct_passthrough` parameter was added. - - :param response: a string or response iterable. - :param status: a string with a status or an integer with the status code. - :param headers: a list of headers or a - :class:`~werkzeug.datastructures.Headers` object. - :param mimetype: the mimetype for the response. See notice above. - :param content_type: the content type for the response. See notice above. - :param direct_passthrough: if set to `True` :meth:`iter_encoded` is not - called before iteration which makes it - possible to pass special iterators through - unchanged (see :func:`wrap_file` for more - details.) - """ - - #: the charset of the response. - charset = "utf-8" - - #: the default status if none is provided. - default_status = 200 - - #: the default mimetype if none is provided. - default_mimetype = "text/plain" - - #: if set to `False` accessing properties on the response object will - #: not try to consume the response iterator and convert it into a list. - #: - #: .. versionadded:: 0.6.2 - #: - #: That attribute was previously called `implicit_seqence_conversion`. - #: (Notice the typo). If you did use this feature, you have to adapt - #: your code to the name change. - implicit_sequence_conversion = True - - #: Should this response object correct the location header to be RFC - #: conformant? This is true by default. - #: - #: .. versionadded:: 0.8 - autocorrect_location_header = True - - #: Should this response object automatically set the content-length - #: header if possible? This is true by default. - #: - #: .. versionadded:: 0.8 - automatically_set_content_length = True - - #: Warn if a cookie header exceeds this size. The default, 4093, should be - #: safely `supported by most browsers `_. A cookie larger than - #: this size will still be sent, but it may be ignored or handled - #: incorrectly by some browsers. Set to 0 to disable this check. - #: - #: .. versionadded:: 0.13 - #: - #: .. _`cookie`: http://browsercookielimits.squawky.net/ - max_cookie_size = 4093 - - def __init__( - self, - response=None, - status=None, - headers=None, - mimetype=None, - content_type=None, - direct_passthrough=False, - ): - if isinstance(headers, Headers): - self.headers = headers - elif not headers: - self.headers = Headers() - else: - self.headers = Headers(headers) - - if content_type is None: - if mimetype is None and "content-type" not in self.headers: - mimetype = self.default_mimetype - if mimetype is not None: - mimetype = get_content_type(mimetype, self.charset) - content_type = mimetype - if content_type is not None: - self.headers["Content-Type"] = content_type - if status is None: - status = self.default_status - if isinstance(status, integer_types): - self.status_code = status - else: - self.status = status - - self.direct_passthrough = direct_passthrough - self._on_close = [] - - # we set the response after the headers so that if a class changes - # the charset attribute, the data is set in the correct charset. - if response is None: - self.response = [] - elif isinstance(response, (text_type, bytes, bytearray)): - self.set_data(response) - else: - self.response = response - - def call_on_close(self, func): - """Adds a function to the internal list of functions that should - be called as part of closing down the response. Since 0.7 this - function also returns the function that was passed so that this - can be used as a decorator. - - .. versionadded:: 0.6 - """ - self._on_close.append(func) - return func - - def __repr__(self): - if self.is_sequence: - body_info = "%d bytes" % sum(map(len, self.iter_encoded())) - else: - body_info = "streamed" if self.is_streamed else "likely-streamed" - return "<%s %s [%s]>" % (self.__class__.__name__, body_info, self.status) - - @classmethod - def force_type(cls, response, environ=None): - """Enforce that the WSGI response is a response object of the current - type. Werkzeug will use the :class:`BaseResponse` internally in many - situations like the exceptions. If you call :meth:`get_response` on an - exception you will get back a regular :class:`BaseResponse` object, even - if you are using a custom subclass. - - This method can enforce a given response type, and it will also - convert arbitrary WSGI callables into response objects if an environ - is provided:: - - # convert a Werkzeug response object into an instance of the - # MyResponseClass subclass. - response = MyResponseClass.force_type(response) - - # convert any WSGI application into a response object - response = MyResponseClass.force_type(response, environ) - - This is especially useful if you want to post-process responses in - the main dispatcher and use functionality provided by your subclass. - - Keep in mind that this will modify response objects in place if - possible! - - :param response: a response object or wsgi application. - :param environ: a WSGI environment object. - :return: a response object. - """ - if not isinstance(response, BaseResponse): - if environ is None: - raise TypeError( - "cannot convert WSGI application into response" - " objects without an environ" - ) - response = BaseResponse(*_run_wsgi_app(response, environ)) - response.__class__ = cls - return response - - @classmethod - def from_app(cls, app, environ, buffered=False): - """Create a new response object from an application output. This - works best if you pass it an application that returns a generator all - the time. Sometimes applications may use the `write()` callable - returned by the `start_response` function. This tries to resolve such - edge cases automatically. But if you don't get the expected output - you should set `buffered` to `True` which enforces buffering. - - :param app: the WSGI application to execute. - :param environ: the WSGI environment to execute against. - :param buffered: set to `True` to enforce buffering. - :return: a response object. - """ - return cls(*_run_wsgi_app(app, environ, buffered)) - - @property - def status_code(self): - """The HTTP status code as a number.""" - return self._status_code - - @status_code.setter - def status_code(self, code): - self._status_code = code - try: - self._status = "%d %s" % (code, HTTP_STATUS_CODES[code].upper()) - except KeyError: - self._status = "%d UNKNOWN" % code - - @property - def status(self): - """The HTTP status code as a string.""" - return self._status - - @status.setter - def status(self, value): - try: - self._status = to_native(value) - except AttributeError: - raise TypeError("Invalid status argument") - - try: - self._status_code = int(self._status.split(None, 1)[0]) - except ValueError: - self._status_code = 0 - self._status = "0 %s" % self._status - except IndexError: - raise ValueError("Empty status argument") - - def get_data(self, as_text=False): - """The string representation of the request body. Whenever you call - this property the request iterable is encoded and flattened. This - can lead to unwanted behavior if you stream big data. - - This behavior can be disabled by setting - :attr:`implicit_sequence_conversion` to `False`. - - If `as_text` is set to `True` the return value will be a decoded - unicode string. - - .. versionadded:: 0.9 - """ - self._ensure_sequence() - rv = b"".join(self.iter_encoded()) - if as_text: - rv = rv.decode(self.charset) - return rv - - def set_data(self, value): - """Sets a new string as response. The value set must be either a - unicode or bytestring. If a unicode string is set it's encoded - automatically to the charset of the response (utf-8 by default). - - .. versionadded:: 0.9 - """ - # if an unicode string is set, it's encoded directly so that we - # can set the content length - if isinstance(value, text_type): - value = value.encode(self.charset) - else: - value = bytes(value) - self.response = [value] - if self.automatically_set_content_length: - self.headers["Content-Length"] = str(len(value)) - - data = property( - get_data, - set_data, - doc="A descriptor that calls :meth:`get_data` and :meth:`set_data`.", - ) - - def calculate_content_length(self): - """Returns the content length if available or `None` otherwise.""" - try: - self._ensure_sequence() - except RuntimeError: - return None - return sum(len(x) for x in self.iter_encoded()) - - def _ensure_sequence(self, mutable=False): - """This method can be called by methods that need a sequence. If - `mutable` is true, it will also ensure that the response sequence - is a standard Python list. - - .. versionadded:: 0.6 - """ - if self.is_sequence: - # if we need a mutable object, we ensure it's a list. - if mutable and not isinstance(self.response, list): - self.response = list(self.response) - return - if self.direct_passthrough: - raise RuntimeError( - "Attempted implicit sequence conversion but the" - " response object is in direct passthrough mode." - ) - if not self.implicit_sequence_conversion: - raise RuntimeError( - "The response object required the iterable to be a" - " sequence, but the implicit conversion was disabled." - " Call make_sequence() yourself." - ) - self.make_sequence() - - def make_sequence(self): - """Converts the response iterator in a list. By default this happens - automatically if required. If `implicit_sequence_conversion` is - disabled, this method is not automatically called and some properties - might raise exceptions. This also encodes all the items. - - .. versionadded:: 0.6 - """ - if not self.is_sequence: - # if we consume an iterable we have to ensure that the close - # method of the iterable is called if available when we tear - # down the response - close = getattr(self.response, "close", None) - self.response = list(self.iter_encoded()) - if close is not None: - self.call_on_close(close) - - def iter_encoded(self): - """Iter the response encoded with the encoding of the response. - If the response object is invoked as WSGI application the return - value of this method is used as application iterator unless - :attr:`direct_passthrough` was activated. - """ - if __debug__: - _warn_if_string(self.response) - # Encode in a separate function so that self.response is fetched - # early. This allows us to wrap the response with the return - # value from get_app_iter or iter_encoded. - return _iter_encoded(self.response, self.charset) - - def set_cookie( - self, - key, - value="", - max_age=None, - expires=None, - path="/", - domain=None, - secure=False, - httponly=False, - samesite=None, - ): - """Sets a cookie. The parameters are the same as in the cookie `Morsel` - object in the Python standard library but it accepts unicode data, too. - - A warning is raised if the size of the cookie header exceeds - :attr:`max_cookie_size`, but the header will still be set. - - :param key: the key (name) of the cookie to be set. - :param value: the value of the cookie. - :param max_age: should be a number of seconds, or `None` (default) if - the cookie should last only as long as the client's - browser session. - :param expires: should be a `datetime` object or UNIX timestamp. - :param path: limits the cookie to a given path, per default it will - span the whole domain. - :param domain: if you want to set a cross-domain cookie. For example, - ``domain=".example.com"`` will set a cookie that is - readable by the domain ``www.example.com``, - ``foo.example.com`` etc. Otherwise, a cookie will only - be readable by the domain that set it. - :param secure: If `True`, the cookie will only be available via HTTPS - :param httponly: disallow JavaScript to access the cookie. This is an - extension to the cookie standard and probably not - supported by all browsers. - :param samesite: Limits the scope of the cookie such that it will only - be attached to requests if those requests are - "same-site". - """ - self.headers.add( - "Set-Cookie", - dump_cookie( - key, - value=value, - max_age=max_age, - expires=expires, - path=path, - domain=domain, - secure=secure, - httponly=httponly, - charset=self.charset, - max_size=self.max_cookie_size, - samesite=samesite, - ), - ) - - def delete_cookie(self, key, path="/", domain=None): - """Delete a cookie. Fails silently if key doesn't exist. - - :param key: the key (name) of the cookie to be deleted. - :param path: if the cookie that should be deleted was limited to a - path, the path has to be defined here. - :param domain: if the cookie that should be deleted was limited to a - domain, that domain has to be defined here. - """ - self.set_cookie(key, expires=0, max_age=0, path=path, domain=domain) - - @property - def is_streamed(self): - """If the response is streamed (the response is not an iterable with - a length information) this property is `True`. In this case streamed - means that there is no information about the number of iterations. - This is usually `True` if a generator is passed to the response object. - - This is useful for checking before applying some sort of post - filtering that should not take place for streamed responses. - """ - try: - len(self.response) - except (TypeError, AttributeError): - return True - return False - - @property - def is_sequence(self): - """If the iterator is buffered, this property will be `True`. A - response object will consider an iterator to be buffered if the - response attribute is a list or tuple. - - .. versionadded:: 0.6 - """ - return isinstance(self.response, (tuple, list)) - - def close(self): - """Close the wrapped response if possible. You can also use the object - in a with statement which will automatically close it. - - .. versionadded:: 0.9 - Can now be used in a with statement. - """ - if hasattr(self.response, "close"): - self.response.close() - for func in self._on_close: - func() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close() - - def freeze(self): - """Call this method if you want to make your response object ready for - being pickled. This buffers the generator if there is one. It will - also set the `Content-Length` header to the length of the body. - - .. versionchanged:: 0.6 - The `Content-Length` header is now set. - """ - # we explicitly set the length to a list of the *encoded* response - # iterator. Even if the implicit sequence conversion is disabled. - self.response = list(self.iter_encoded()) - self.headers["Content-Length"] = str(sum(map(len, self.response))) - - def get_wsgi_headers(self, environ): - """This is automatically called right before the response is started - and returns headers modified for the given environment. It returns a - copy of the headers from the response with some modifications applied - if necessary. - - For example the location header (if present) is joined with the root - URL of the environment. Also the content length is automatically set - to zero here for certain status codes. - - .. versionchanged:: 0.6 - Previously that function was called `fix_headers` and modified - the response object in place. Also since 0.6, IRIs in location - and content-location headers are handled properly. - - Also starting with 0.6, Werkzeug will attempt to set the content - length if it is able to figure it out on its own. This is the - case if all the strings in the response iterable are already - encoded and the iterable is buffered. - - :param environ: the WSGI environment of the request. - :return: returns a new :class:`~werkzeug.datastructures.Headers` - object. - """ - headers = Headers(self.headers) - location = None - content_location = None - content_length = None - status = self.status_code - - # iterate over the headers to find all values in one go. Because - # get_wsgi_headers is used each response that gives us a tiny - # speedup. - for key, value in headers: - ikey = key.lower() - if ikey == u"location": - location = value - elif ikey == u"content-location": - content_location = value - elif ikey == u"content-length": - content_length = value - - # make sure the location header is an absolute URL - if location is not None: - old_location = location - if isinstance(location, text_type): - # Safe conversion is necessary here as we might redirect - # to a broken URI scheme (for instance itms-services). - location = iri_to_uri(location, safe_conversion=True) - - if self.autocorrect_location_header: - current_url = get_current_url(environ, strip_querystring=True) - if isinstance(current_url, text_type): - current_url = iri_to_uri(current_url) - location = url_join(current_url, location) - if location != old_location: - headers["Location"] = location - - # make sure the content location is a URL - if content_location is not None and isinstance(content_location, text_type): - headers["Content-Location"] = iri_to_uri(content_location) - - if 100 <= status < 200 or status == 204: - # Per section 3.3.2 of RFC 7230, "a server MUST NOT send a - # Content-Length header field in any response with a status - # code of 1xx (Informational) or 204 (No Content)." - headers.remove("Content-Length") - elif status == 304: - remove_entity_headers(headers) - - # if we can determine the content length automatically, we - # should try to do that. But only if this does not involve - # flattening the iterator or encoding of unicode strings in - # the response. We however should not do that if we have a 304 - # response. - if ( - self.automatically_set_content_length - and self.is_sequence - and content_length is None - and status not in (204, 304) - and not (100 <= status < 200) - ): - try: - content_length = sum(len(to_bytes(x, "ascii")) for x in self.response) - except UnicodeError: - # aha, something non-bytestringy in there, too bad, we - # can't safely figure out the length of the response. - pass - else: - headers["Content-Length"] = str(content_length) - - return headers - - def get_app_iter(self, environ): - """Returns the application iterator for the given environ. Depending - on the request method and the current status code the return value - might be an empty response rather than the one from the response. - - If the request method is `HEAD` or the status code is in a range - where the HTTP specification requires an empty response, an empty - iterable is returned. - - .. versionadded:: 0.6 - - :param environ: the WSGI environment of the request. - :return: a response iterable. - """ - status = self.status_code - if ( - environ["REQUEST_METHOD"] == "HEAD" - or 100 <= status < 200 - or status in (204, 304) - ): - iterable = () - elif self.direct_passthrough: - if __debug__: - _warn_if_string(self.response) - return self.response - else: - iterable = self.iter_encoded() - return ClosingIterator(iterable, self.close) - - def get_wsgi_response(self, environ): - """Returns the final WSGI response as tuple. The first item in - the tuple is the application iterator, the second the status and - the third the list of headers. The response returned is created - specially for the given environment. For example if the request - method in the WSGI environment is ``'HEAD'`` the response will - be empty and only the headers and status code will be present. - - .. versionadded:: 0.6 - - :param environ: the WSGI environment of the request. - :return: an ``(app_iter, status, headers)`` tuple. - """ - headers = self.get_wsgi_headers(environ) - app_iter = self.get_app_iter(environ) - return app_iter, self.status, headers.to_wsgi_list() - - def __call__(self, environ, start_response): - """Process this response as WSGI application. - - :param environ: the WSGI environment. - :param start_response: the response callable provided by the WSGI - server. - :return: an application iterator - """ - app_iter, status, headers = self.get_wsgi_response(environ) - start_response(status, headers) - return app_iter diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/common_descriptors.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/common_descriptors.py deleted file mode 100644 index f169959..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/common_descriptors.py +++ /dev/null @@ -1,341 +0,0 @@ -from datetime import datetime -from datetime import timedelta - -from .._compat import string_types -from ..datastructures import CallbackDict -from ..http import dump_age -from ..http import dump_csp_header -from ..http import dump_header -from ..http import dump_options_header -from ..http import http_date -from ..http import parse_age -from ..http import parse_csp_header -from ..http import parse_date -from ..http import parse_options_header -from ..http import parse_set_header -from ..utils import cached_property -from ..utils import environ_property -from ..utils import get_content_type -from ..utils import header_property -from ..wsgi import get_content_length - - -class CommonRequestDescriptorsMixin(object): - """A mixin for :class:`BaseRequest` subclasses. Request objects that - mix this class in will automatically get descriptors for a couple of - HTTP headers with automatic type conversion. - - .. versionadded:: 0.5 - """ - - content_type = environ_property( - "CONTENT_TYPE", - doc="""The Content-Type entity-header field indicates the media - type of the entity-body sent to the recipient or, in the case of - the HEAD method, the media type that would have been sent had - the request been a GET.""", - ) - - @cached_property - def content_length(self): - """The Content-Length entity-header field indicates the size of the - entity-body in bytes or, in the case of the HEAD method, the size of - the entity-body that would have been sent had the request been a - GET. - """ - return get_content_length(self.environ) - - content_encoding = environ_property( - "HTTP_CONTENT_ENCODING", - doc="""The Content-Encoding entity-header field is used as a - modifier to the media-type. When present, its value indicates - what additional content codings have been applied to the - entity-body, and thus what decoding mechanisms must be applied - in order to obtain the media-type referenced by the Content-Type - header field. - - .. versionadded:: 0.9""", - ) - content_md5 = environ_property( - "HTTP_CONTENT_MD5", - doc="""The Content-MD5 entity-header field, as defined in - RFC 1864, is an MD5 digest of the entity-body for the purpose of - providing an end-to-end message integrity check (MIC) of the - entity-body. (Note: a MIC is good for detecting accidental - modification of the entity-body in transit, but is not proof - against malicious attacks.) - - .. versionadded:: 0.9""", - ) - referrer = environ_property( - "HTTP_REFERER", - doc="""The Referer[sic] request-header field allows the client - to specify, for the server's benefit, the address (URI) of the - resource from which the Request-URI was obtained (the - "referrer", although the header field is misspelled).""", - ) - date = environ_property( - "HTTP_DATE", - None, - parse_date, - doc="""The Date general-header field represents the date and - time at which the message was originated, having the same - semantics as orig-date in RFC 822.""", - ) - max_forwards = environ_property( - "HTTP_MAX_FORWARDS", - None, - int, - doc="""The Max-Forwards request-header field provides a - mechanism with the TRACE and OPTIONS methods to limit the number - of proxies or gateways that can forward the request to the next - inbound server.""", - ) - - def _parse_content_type(self): - if not hasattr(self, "_parsed_content_type"): - self._parsed_content_type = parse_options_header( - self.environ.get("CONTENT_TYPE", "") - ) - - @property - def mimetype(self): - """Like :attr:`content_type`, but without parameters (eg, without - charset, type etc.) and always lowercase. For example if the content - type is ``text/HTML; charset=utf-8`` the mimetype would be - ``'text/html'``. - """ - self._parse_content_type() - return self._parsed_content_type[0].lower() - - @property - def mimetype_params(self): - """The mimetype parameters as dict. For example if the content - type is ``text/html; charset=utf-8`` the params would be - ``{'charset': 'utf-8'}``. - """ - self._parse_content_type() - return self._parsed_content_type[1] - - @cached_property - def pragma(self): - """The Pragma general-header field is used to include - implementation-specific directives that might apply to any recipient - along the request/response chain. All pragma directives specify - optional behavior from the viewpoint of the protocol; however, some - systems MAY require that behavior be consistent with the directives. - """ - return parse_set_header(self.environ.get("HTTP_PRAGMA", "")) - - -class CommonResponseDescriptorsMixin(object): - """A mixin for :class:`BaseResponse` subclasses. Response objects that - mix this class in will automatically get descriptors for a couple of - HTTP headers with automatic type conversion. - """ - - @property - def mimetype(self): - """The mimetype (content type without charset etc.)""" - ct = self.headers.get("content-type") - if ct: - return ct.split(";")[0].strip() - - @mimetype.setter - def mimetype(self, value): - self.headers["Content-Type"] = get_content_type(value, self.charset) - - @property - def mimetype_params(self): - """The mimetype parameters as dict. For example if the - content type is ``text/html; charset=utf-8`` the params would be - ``{'charset': 'utf-8'}``. - - .. versionadded:: 0.5 - """ - - def on_update(d): - self.headers["Content-Type"] = dump_options_header(self.mimetype, d) - - d = parse_options_header(self.headers.get("content-type", ""))[1] - return CallbackDict(d, on_update) - - location = header_property( - "Location", - doc="""The Location response-header field is used to redirect - the recipient to a location other than the Request-URI for - completion of the request or identification of a new - resource.""", - ) - age = header_property( - "Age", - None, - parse_age, - dump_age, - doc="""The Age response-header field conveys the sender's - estimate of the amount of time since the response (or its - revalidation) was generated at the origin server. - - Age values are non-negative decimal integers, representing time - in seconds.""", - ) - content_type = header_property( - "Content-Type", - doc="""The Content-Type entity-header field indicates the media - type of the entity-body sent to the recipient or, in the case of - the HEAD method, the media type that would have been sent had - the request been a GET.""", - ) - content_length = header_property( - "Content-Length", - None, - int, - str, - doc="""The Content-Length entity-header field indicates the size - of the entity-body, in decimal number of OCTETs, sent to the - recipient or, in the case of the HEAD method, the size of the - entity-body that would have been sent had the request been a - GET.""", - ) - content_location = header_property( - "Content-Location", - doc="""The Content-Location entity-header field MAY be used to - supply the resource location for the entity enclosed in the - message when that entity is accessible from a location separate - from the requested resource's URI.""", - ) - content_encoding = header_property( - "Content-Encoding", - doc="""The Content-Encoding entity-header field is used as a - modifier to the media-type. When present, its value indicates - what additional content codings have been applied to the - entity-body, and thus what decoding mechanisms must be applied - in order to obtain the media-type referenced by the Content-Type - header field.""", - ) - content_md5 = header_property( - "Content-MD5", - doc="""The Content-MD5 entity-header field, as defined in - RFC 1864, is an MD5 digest of the entity-body for the purpose of - providing an end-to-end message integrity check (MIC) of the - entity-body. (Note: a MIC is good for detecting accidental - modification of the entity-body in transit, but is not proof - against malicious attacks.)""", - ) - content_security_policy = header_property( - "Content-Security-Policy", - None, - parse_csp_header, - dump_csp_header, - doc="""The Content-Security-Policy header adds an additional layer of - security to help detect and mitigate certain types of attacks.""", - ) - content_security_policy_report_only = header_property( - "Content-Security-Policy-Report-Only", - None, - parse_csp_header, - dump_csp_header, - doc="""The Content-Security-Policy-Report-Only header adds a csp policy - that is not enforced but is reported thereby helping detect - certain types of attacks.""", - ) - date = header_property( - "Date", - None, - parse_date, - http_date, - doc="""The Date general-header field represents the date and - time at which the message was originated, having the same - semantics as orig-date in RFC 822.""", - ) - expires = header_property( - "Expires", - None, - parse_date, - http_date, - doc="""The Expires entity-header field gives the date/time after - which the response is considered stale. A stale cache entry may - not normally be returned by a cache.""", - ) - last_modified = header_property( - "Last-Modified", - None, - parse_date, - http_date, - doc="""The Last-Modified entity-header field indicates the date - and time at which the origin server believes the variant was - last modified.""", - ) - - @property - def retry_after(self): - """The Retry-After response-header field can be used with a - 503 (Service Unavailable) response to indicate how long the - service is expected to be unavailable to the requesting client. - - Time in seconds until expiration or date. - """ - value = self.headers.get("retry-after") - if value is None: - return - elif value.isdigit(): - return datetime.utcnow() + timedelta(seconds=int(value)) - return parse_date(value) - - @retry_after.setter - def retry_after(self, value): - if value is None: - if "retry-after" in self.headers: - del self.headers["retry-after"] - return - elif isinstance(value, datetime): - value = http_date(value) - else: - value = str(value) - self.headers["Retry-After"] = value - - def _set_property(name, doc=None): # noqa: B902 - def fget(self): - def on_update(header_set): - if not header_set and name in self.headers: - del self.headers[name] - elif header_set: - self.headers[name] = header_set.to_header() - - return parse_set_header(self.headers.get(name), on_update) - - def fset(self, value): - if not value: - del self.headers[name] - elif isinstance(value, string_types): - self.headers[name] = value - else: - self.headers[name] = dump_header(value) - - return property(fget, fset, doc=doc) - - vary = _set_property( - "Vary", - doc="""The Vary field value indicates the set of request-header - fields that fully determines, while the response is fresh, - whether a cache is permitted to use the response to reply to a - subsequent request without revalidation.""", - ) - content_language = _set_property( - "Content-Language", - doc="""The Content-Language entity-header field describes the - natural language(s) of the intended audience for the enclosed - entity. Note that this might not be equivalent to all the - languages used within the entity-body.""", - ) - allow = _set_property( - "Allow", - doc="""The Allow entity-header field lists the set of methods - supported by the resource identified by the Request-URI. The - purpose of this field is strictly to inform the recipient of - valid methods associated with the resource. An Allow header - field MUST be present in a 405 (Method Not Allowed) - response.""", - ) - - del _set_property diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/cors.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/cors.py deleted file mode 100644 index 502fcf1..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/cors.py +++ /dev/null @@ -1,100 +0,0 @@ -from ..http import dump_header -from ..http import parse_set_header -from ..utils import environ_property -from ..utils import header_property - - -class CORSRequestMixin(object): - """A mixin for :class:`~werkzeug.wrappers.BaseRequest` subclasses - that adds descriptors for Cross Origin Resource Sharing (CORS) - headers. - - .. versionadded:: 1.0 - """ - - origin = environ_property( - "HTTP_ORIGIN", - doc=( - "The host that the request originated from. Set" - " :attr:`~CORSResponseMixin.access_control_allow_origin` on" - " the response to indicate which origins are allowed." - ), - ) - - access_control_request_headers = environ_property( - "HTTP_ACCESS_CONTROL_REQUEST_HEADERS", - load_func=parse_set_header, - doc=( - "Sent with a preflight request to indicate which headers" - " will be sent with the cross origin request. Set" - " :attr:`~CORSResponseMixin.access_control_allow_headers`" - " on the response to indicate which headers are allowed." - ), - ) - - access_control_request_method = environ_property( - "HTTP_ACCESS_CONTROL_REQUEST_METHOD", - doc=( - "Sent with a preflight request to indicate which method" - " will be used for the cross origin request. Set" - " :attr:`~CORSResponseMixin.access_control_allow_methods`" - " on the response to indicate which methods are allowed." - ), - ) - - -class CORSResponseMixin(object): - """A mixin for :class:`~werkzeug.wrappers.BaseResponse` subclasses - that adds descriptors for Cross Origin Resource Sharing (CORS) - headers. - - .. versionadded:: 1.0 - """ - - @property - def access_control_allow_credentials(self): - """Whether credentials can be shared by the browser to - JavaScript code. As part of the preflight request it indicates - whether credentials can be used on the cross origin request. - """ - return "Access-Control-Allow-Credentials" in self.headers - - @access_control_allow_credentials.setter - def access_control_allow_credentials(self, value): - if value is True: - self.headers["Access-Control-Allow-Credentials"] = "true" - else: - self.headers.pop("Access-Control-Allow-Credentials", None) - - access_control_allow_headers = header_property( - "Access-Control-Allow-Headers", - load_func=parse_set_header, - dump_func=dump_header, - doc="Which headers can be sent with the cross origin request.", - ) - - access_control_allow_methods = header_property( - "Access-Control-Allow-Methods", - load_func=parse_set_header, - dump_func=dump_header, - doc="Which methods can be used for the cross origin request.", - ) - - access_control_allow_origin = header_property( - "Access-Control-Allow-Origin", - doc="The origin or '*' for any origin that may make cross origin requests.", - ) - - access_control_expose_headers = header_property( - "Access-Control-Expose-Headers", - load_func=parse_set_header, - dump_func=dump_header, - doc="Which headers can be shared by the browser to JavaScript code.", - ) - - access_control_max_age = header_property( - "Access-Control-Max-Age", - load_func=int, - dump_func=str, - doc="The maximum age in seconds the access control settings can be cached for.", - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/etag.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/etag.py deleted file mode 100644 index 460629b..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/etag.py +++ /dev/null @@ -1,304 +0,0 @@ -from .._compat import string_types -from .._internal import _get_environ -from ..datastructures import ContentRange -from ..datastructures import RequestCacheControl -from ..datastructures import ResponseCacheControl -from ..http import generate_etag -from ..http import http_date -from ..http import is_resource_modified -from ..http import parse_cache_control_header -from ..http import parse_content_range_header -from ..http import parse_date -from ..http import parse_etags -from ..http import parse_if_range_header -from ..http import parse_range_header -from ..http import quote_etag -from ..http import unquote_etag -from ..utils import cached_property -from ..utils import header_property -from ..wrappers.base_response import _clean_accept_ranges -from ..wsgi import _RangeWrapper - - -class ETagRequestMixin(object): - """Add entity tag and cache descriptors to a request object or object with - a WSGI environment available as :attr:`~BaseRequest.environ`. This not - only provides access to etags but also to the cache control header. - """ - - @cached_property - def cache_control(self): - """A :class:`~werkzeug.datastructures.RequestCacheControl` object - for the incoming cache control headers. - """ - cache_control = self.environ.get("HTTP_CACHE_CONTROL") - return parse_cache_control_header(cache_control, None, RequestCacheControl) - - @cached_property - def if_match(self): - """An object containing all the etags in the `If-Match` header. - - :rtype: :class:`~werkzeug.datastructures.ETags` - """ - return parse_etags(self.environ.get("HTTP_IF_MATCH")) - - @cached_property - def if_none_match(self): - """An object containing all the etags in the `If-None-Match` header. - - :rtype: :class:`~werkzeug.datastructures.ETags` - """ - return parse_etags(self.environ.get("HTTP_IF_NONE_MATCH")) - - @cached_property - def if_modified_since(self): - """The parsed `If-Modified-Since` header as datetime object.""" - return parse_date(self.environ.get("HTTP_IF_MODIFIED_SINCE")) - - @cached_property - def if_unmodified_since(self): - """The parsed `If-Unmodified-Since` header as datetime object.""" - return parse_date(self.environ.get("HTTP_IF_UNMODIFIED_SINCE")) - - @cached_property - def if_range(self): - """The parsed `If-Range` header. - - .. versionadded:: 0.7 - - :rtype: :class:`~werkzeug.datastructures.IfRange` - """ - return parse_if_range_header(self.environ.get("HTTP_IF_RANGE")) - - @cached_property - def range(self): - """The parsed `Range` header. - - .. versionadded:: 0.7 - - :rtype: :class:`~werkzeug.datastructures.Range` - """ - return parse_range_header(self.environ.get("HTTP_RANGE")) - - -class ETagResponseMixin(object): - """Adds extra functionality to a response object for etag and cache - handling. This mixin requires an object with at least a `headers` - object that implements a dict like interface similar to - :class:`~werkzeug.datastructures.Headers`. - - If you want the :meth:`freeze` method to automatically add an etag, you - have to mixin this method before the response base class. The default - response class does not do that. - """ - - @property - def cache_control(self): - """The Cache-Control general-header field is used to specify - directives that MUST be obeyed by all caching mechanisms along the - request/response chain. - """ - - def on_update(cache_control): - if not cache_control and "cache-control" in self.headers: - del self.headers["cache-control"] - elif cache_control: - self.headers["Cache-Control"] = cache_control.to_header() - - return parse_cache_control_header( - self.headers.get("cache-control"), on_update, ResponseCacheControl - ) - - def _wrap_response(self, start, length): - """Wrap existing Response in case of Range Request context.""" - if self.status_code == 206: - self.response = _RangeWrapper(self.response, start, length) - - def _is_range_request_processable(self, environ): - """Return ``True`` if `Range` header is present and if underlying - resource is considered unchanged when compared with `If-Range` header. - """ - return ( - "HTTP_IF_RANGE" not in environ - or not is_resource_modified( - environ, - self.headers.get("etag"), - None, - self.headers.get("last-modified"), - ignore_if_range=False, - ) - ) and "HTTP_RANGE" in environ - - def _process_range_request(self, environ, complete_length=None, accept_ranges=None): - """Handle Range Request related headers (RFC7233). If `Accept-Ranges` - header is valid, and Range Request is processable, we set the headers - as described by the RFC, and wrap the underlying response in a - RangeWrapper. - - Returns ``True`` if Range Request can be fulfilled, ``False`` otherwise. - - :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` - if `Range` header could not be parsed or satisfied. - """ - from ..exceptions import RequestedRangeNotSatisfiable - - if ( - accept_ranges is None - or complete_length is None - or not self._is_range_request_processable(environ) - ): - return False - - parsed_range = parse_range_header(environ.get("HTTP_RANGE")) - - if parsed_range is None: - raise RequestedRangeNotSatisfiable(complete_length) - - range_tuple = parsed_range.range_for_length(complete_length) - content_range_header = parsed_range.to_content_range_header(complete_length) - - if range_tuple is None or content_range_header is None: - raise RequestedRangeNotSatisfiable(complete_length) - - content_length = range_tuple[1] - range_tuple[0] - self.headers["Content-Length"] = content_length - self.headers["Accept-Ranges"] = accept_ranges - self.content_range = content_range_header - self.status_code = 206 - self._wrap_response(range_tuple[0], content_length) - return True - - def make_conditional( - self, request_or_environ, accept_ranges=False, complete_length=None - ): - """Make the response conditional to the request. This method works - best if an etag was defined for the response already. The `add_etag` - method can be used to do that. If called without etag just the date - header is set. - - This does nothing if the request method in the request or environ is - anything but GET or HEAD. - - For optimal performance when handling range requests, it's recommended - that your response data object implements `seekable`, `seek` and `tell` - methods as described by :py:class:`io.IOBase`. Objects returned by - :meth:`~werkzeug.wsgi.wrap_file` automatically implement those methods. - - It does not remove the body of the response because that's something - the :meth:`__call__` function does for us automatically. - - Returns self so that you can do ``return resp.make_conditional(req)`` - but modifies the object in-place. - - :param request_or_environ: a request object or WSGI environment to be - used to make the response conditional - against. - :param accept_ranges: This parameter dictates the value of - `Accept-Ranges` header. If ``False`` (default), - the header is not set. If ``True``, it will be set - to ``"bytes"``. If ``None``, it will be set to - ``"none"``. If it's a string, it will use this - value. - :param complete_length: Will be used only in valid Range Requests. - It will set `Content-Range` complete length - value and compute `Content-Length` real value. - This parameter is mandatory for successful - Range Requests completion. - :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` - if `Range` header could not be parsed or satisfied. - """ - environ = _get_environ(request_or_environ) - if environ["REQUEST_METHOD"] in ("GET", "HEAD"): - # if the date is not in the headers, add it now. We however - # will not override an already existing header. Unfortunately - # this header will be overriden by many WSGI servers including - # wsgiref. - if "date" not in self.headers: - self.headers["Date"] = http_date() - accept_ranges = _clean_accept_ranges(accept_ranges) - is206 = self._process_range_request(environ, complete_length, accept_ranges) - if not is206 and not is_resource_modified( - environ, - self.headers.get("etag"), - None, - self.headers.get("last-modified"), - ): - if parse_etags(environ.get("HTTP_IF_MATCH")): - self.status_code = 412 - else: - self.status_code = 304 - if ( - self.automatically_set_content_length - and "content-length" not in self.headers - ): - length = self.calculate_content_length() - if length is not None: - self.headers["Content-Length"] = length - return self - - def add_etag(self, overwrite=False, weak=False): - """Add an etag for the current response if there is none yet.""" - if overwrite or "etag" not in self.headers: - self.set_etag(generate_etag(self.get_data()), weak) - - def set_etag(self, etag, weak=False): - """Set the etag, and override the old one if there was one.""" - self.headers["ETag"] = quote_etag(etag, weak) - - def get_etag(self): - """Return a tuple in the form ``(etag, is_weak)``. If there is no - ETag the return value is ``(None, None)``. - """ - return unquote_etag(self.headers.get("ETag")) - - def freeze(self, no_etag=False): - """Call this method if you want to make your response object ready for - pickeling. This buffers the generator if there is one. This also - sets the etag unless `no_etag` is set to `True`. - """ - if not no_etag: - self.add_etag() - super(ETagResponseMixin, self).freeze() - - accept_ranges = header_property( - "Accept-Ranges", - doc="""The `Accept-Ranges` header. Even though the name would - indicate that multiple values are supported, it must be one - string token only. - - The values ``'bytes'`` and ``'none'`` are common. - - .. versionadded:: 0.7""", - ) - - @property - def content_range(self): - """The ``Content-Range`` header as a - :class:`~werkzeug.datastructures.ContentRange` object. Available - even if the header is not set. - - .. versionadded:: 0.7 - """ - - def on_update(rng): - if not rng: - del self.headers["content-range"] - else: - self.headers["Content-Range"] = rng.to_header() - - rv = parse_content_range_header(self.headers.get("content-range"), on_update) - # always provide a content range object to make the descriptor - # more user friendly. It provides an unset() method that can be - # used to remove the header quickly. - if rv is None: - rv = ContentRange(None, None, None, on_update=on_update) - return rv - - @content_range.setter - def content_range(self, value): - if not value: - del self.headers["content-range"] - elif isinstance(value, string_types): - self.headers["Content-Range"] = value - else: - self.headers["Content-Range"] = value.to_header() diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/json.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/json.py deleted file mode 100644 index 6d5dc33..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/json.py +++ /dev/null @@ -1,145 +0,0 @@ -from __future__ import absolute_import - -import datetime -import uuid - -from .._compat import text_type -from ..exceptions import BadRequest -from ..utils import detect_utf_encoding - -try: - import simplejson as _json -except ImportError: - import json as _json - - -class _JSONModule(object): - @staticmethod - def _default(o): - if isinstance(o, datetime.date): - return o.isoformat() - - if isinstance(o, uuid.UUID): - return str(o) - - if hasattr(o, "__html__"): - return text_type(o.__html__()) - - raise TypeError() - - @classmethod - def dumps(cls, obj, **kw): - kw.setdefault("separators", (",", ":")) - kw.setdefault("default", cls._default) - kw.setdefault("sort_keys", True) - return _json.dumps(obj, **kw) - - @staticmethod - def loads(s, **kw): - if isinstance(s, bytes): - # Needed for Python < 3.6 - encoding = detect_utf_encoding(s) - s = s.decode(encoding) - - return _json.loads(s, **kw) - - -class JSONMixin(object): - """Mixin to parse :attr:`data` as JSON. Can be mixed in for both - :class:`~werkzeug.wrappers.Request` and - :class:`~werkzeug.wrappers.Response` classes. - - If `simplejson`_ is installed it is preferred over Python's built-in - :mod:`json` module. - - .. _simplejson: https://simplejson.readthedocs.io/en/latest/ - """ - - #: A module or other object that has ``dumps`` and ``loads`` - #: functions that match the API of the built-in :mod:`json` module. - json_module = _JSONModule - - @property - def json(self): - """The parsed JSON data if :attr:`mimetype` indicates JSON - (:mimetype:`application/json`, see :meth:`is_json`). - - Calls :meth:`get_json` with default arguments. - """ - return self.get_json() - - @property - def is_json(self): - """Check if the mimetype indicates JSON data, either - :mimetype:`application/json` or :mimetype:`application/*+json`. - """ - mt = self.mimetype - return ( - mt == "application/json" - or mt.startswith("application/") - and mt.endswith("+json") - ) - - def _get_data_for_json(self, cache): - try: - return self.get_data(cache=cache) - except TypeError: - # Response doesn't have cache param. - return self.get_data() - - # Cached values for ``(silent=False, silent=True)``. Initialized - # with sentinel values. - _cached_json = (Ellipsis, Ellipsis) - - def get_json(self, force=False, silent=False, cache=True): - """Parse :attr:`data` as JSON. - - If the mimetype does not indicate JSON - (:mimetype:`application/json`, see :meth:`is_json`), this - returns ``None``. - - If parsing fails, :meth:`on_json_loading_failed` is called and - its return value is used as the return value. - - :param force: Ignore the mimetype and always try to parse JSON. - :param silent: Silence parsing errors and return ``None`` - instead. - :param cache: Store the parsed JSON to return for subsequent - calls. - """ - if cache and self._cached_json[silent] is not Ellipsis: - return self._cached_json[silent] - - if not (force or self.is_json): - return None - - data = self._get_data_for_json(cache=cache) - - try: - rv = self.json_module.loads(data) - except ValueError as e: - if silent: - rv = None - - if cache: - normal_rv, _ = self._cached_json - self._cached_json = (normal_rv, rv) - else: - rv = self.on_json_loading_failed(e) - - if cache: - _, silent_rv = self._cached_json - self._cached_json = (rv, silent_rv) - else: - if cache: - self._cached_json = (rv, rv) - - return rv - - def on_json_loading_failed(self, e): - """Called if :meth:`get_json` parsing fails and isn't silenced. - If this method returns a value, it is used as the return value - for :meth:`get_json`. The default implementation raises - :exc:`~werkzeug.exceptions.BadRequest`. - """ - raise BadRequest("Failed to decode JSON object: {0}".format(e)) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/request.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/request.py deleted file mode 100644 index 5c2fe10..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/request.py +++ /dev/null @@ -1,49 +0,0 @@ -from .accept import AcceptMixin -from .auth import AuthorizationMixin -from .base_request import BaseRequest -from .common_descriptors import CommonRequestDescriptorsMixin -from .cors import CORSRequestMixin -from .etag import ETagRequestMixin -from .user_agent import UserAgentMixin - - -class Request( - BaseRequest, - AcceptMixin, - ETagRequestMixin, - UserAgentMixin, - AuthorizationMixin, - CORSRequestMixin, - CommonRequestDescriptorsMixin, -): - """Full featured request object implementing the following mixins: - - - :class:`AcceptMixin` for accept header parsing - - :class:`ETagRequestMixin` for etag and cache control handling - - :class:`UserAgentMixin` for user agent introspection - - :class:`AuthorizationMixin` for http auth handling - - :class:`~werkzeug.wrappers.cors.CORSRequestMixin` for Cross - Origin Resource Sharing headers - - :class:`CommonRequestDescriptorsMixin` for common headers - - """ - - -class StreamOnlyMixin(object): - """If mixed in before the request object this will change the behavior - of it to disable handling of form parsing. This disables the - :attr:`files`, :attr:`form` attributes and will just provide a - :attr:`stream` attribute that however is always available. - - .. versionadded:: 0.9 - """ - - disable_data_descriptor = True - want_form_data_parsed = False - - -class PlainRequest(StreamOnlyMixin, Request): - """A request object without special form parsing capabilities. - - .. versionadded:: 0.9 - """ diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/response.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/response.py deleted file mode 100644 index 8f190f7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/response.py +++ /dev/null @@ -1,84 +0,0 @@ -from ..utils import cached_property -from .auth import WWWAuthenticateMixin -from .base_response import BaseResponse -from .common_descriptors import CommonResponseDescriptorsMixin -from .cors import CORSResponseMixin -from .etag import ETagResponseMixin - - -class ResponseStream(object): - """A file descriptor like object used by the :class:`ResponseStreamMixin` to - represent the body of the stream. It directly pushes into the response - iterable of the response object. - """ - - mode = "wb+" - - def __init__(self, response): - self.response = response - self.closed = False - - def write(self, value): - if self.closed: - raise ValueError("I/O operation on closed file") - self.response._ensure_sequence(mutable=True) - self.response.response.append(value) - self.response.headers.pop("Content-Length", None) - return len(value) - - def writelines(self, seq): - for item in seq: - self.write(item) - - def close(self): - self.closed = True - - def flush(self): - if self.closed: - raise ValueError("I/O operation on closed file") - - def isatty(self): - if self.closed: - raise ValueError("I/O operation on closed file") - return False - - def tell(self): - self.response._ensure_sequence() - return sum(map(len, self.response.response)) - - @property - def encoding(self): - return self.response.charset - - -class ResponseStreamMixin(object): - """Mixin for :class:`BaseResponse` subclasses. Classes that inherit from - this mixin will automatically get a :attr:`stream` property that provides - a write-only interface to the response iterable. - """ - - @cached_property - def stream(self): - """The response iterable as write-only stream.""" - return ResponseStream(self) - - -class Response( - BaseResponse, - ETagResponseMixin, - WWWAuthenticateMixin, - CORSResponseMixin, - ResponseStreamMixin, - CommonResponseDescriptorsMixin, -): - """Full featured response object implementing the following mixins: - - - :class:`ETagResponseMixin` for etag and cache control handling - - :class:`WWWAuthenticateMixin` for HTTP authentication support - - :class:`~werkzeug.wrappers.cors.CORSResponseMixin` for Cross - Origin Resource Sharing headers - - :class:`ResponseStreamMixin` to add support for the ``stream`` - property - - :class:`CommonResponseDescriptorsMixin` for various HTTP - descriptors - """ diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/user_agent.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/user_agent.py deleted file mode 100644 index a32d8ac..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wrappers/user_agent.py +++ /dev/null @@ -1,14 +0,0 @@ -from ..useragents import UserAgent -from ..utils import cached_property - - -class UserAgentMixin(object): - """Adds a `user_agent` attribute to the request object which - contains the parsed user agent of the browser that triggered the - request as a :class:`~werkzeug.useragents.UserAgent` object. - """ - - @cached_property - def user_agent(self): - """The current user agent.""" - return UserAgent(self.environ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wsgi.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wsgi.py deleted file mode 100644 index aa4e713..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/werkzeug/wsgi.py +++ /dev/null @@ -1,1000 +0,0 @@ -# -*- coding: utf-8 -*- -""" - werkzeug.wsgi - ~~~~~~~~~~~~~ - - This module implements WSGI related helpers. - - :copyright: 2007 Pallets - :license: BSD-3-Clause -""" -import io -import re -from functools import partial -from functools import update_wrapper -from itertools import chain - -from ._compat import BytesIO -from ._compat import implements_iterator -from ._compat import make_literal_wrapper -from ._compat import string_types -from ._compat import text_type -from ._compat import to_bytes -from ._compat import to_unicode -from ._compat import try_coerce_native -from ._compat import wsgi_get_bytes -from ._internal import _encode_idna -from .urls import uri_to_iri -from .urls import url_join -from .urls import url_parse -from .urls import url_quote - - -def responder(f): - """Marks a function as responder. Decorate a function with it and it - will automatically call the return value as WSGI application. - - Example:: - - @responder - def application(environ, start_response): - return Response('Hello World!') - """ - return update_wrapper(lambda *a: f(*a)(*a[-2:]), f) - - -def get_current_url( - environ, - root_only=False, - strip_querystring=False, - host_only=False, - trusted_hosts=None, -): - """A handy helper function that recreates the full URL as IRI for the - current request or parts of it. Here's an example: - - >>> from werkzeug.test import create_environ - >>> env = create_environ("/?param=foo", "http://localhost/script") - >>> get_current_url(env) - 'http://localhost/script/?param=foo' - >>> get_current_url(env, root_only=True) - 'http://localhost/script/' - >>> get_current_url(env, host_only=True) - 'http://localhost/' - >>> get_current_url(env, strip_querystring=True) - 'http://localhost/script/' - - This optionally it verifies that the host is in a list of trusted hosts. - If the host is not in there it will raise a - :exc:`~werkzeug.exceptions.SecurityError`. - - Note that the string returned might contain unicode characters as the - representation is an IRI not an URI. If you need an ASCII only - representation you can use the :func:`~werkzeug.urls.iri_to_uri` - function: - - >>> from werkzeug.urls import iri_to_uri - >>> iri_to_uri(get_current_url(env)) - 'http://localhost/script/?param=foo' - - :param environ: the WSGI environment to get the current URL from. - :param root_only: set `True` if you only want the root URL. - :param strip_querystring: set to `True` if you don't want the querystring. - :param host_only: set to `True` if the host URL should be returned. - :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted` - for more information. - """ - tmp = [environ["wsgi.url_scheme"], "://", get_host(environ, trusted_hosts)] - cat = tmp.append - if host_only: - return uri_to_iri("".join(tmp) + "/") - cat(url_quote(wsgi_get_bytes(environ.get("SCRIPT_NAME", ""))).rstrip("/")) - cat("/") - if not root_only: - cat(url_quote(wsgi_get_bytes(environ.get("PATH_INFO", "")).lstrip(b"/"))) - if not strip_querystring: - qs = get_query_string(environ) - if qs: - cat("?" + qs) - return uri_to_iri("".join(tmp)) - - -def host_is_trusted(hostname, trusted_list): - """Checks if a host is trusted against a list. This also takes care - of port normalization. - - .. versionadded:: 0.9 - - :param hostname: the hostname to check - :param trusted_list: a list of hostnames to check against. If a - hostname starts with a dot it will match against - all subdomains as well. - """ - if not hostname: - return False - - if isinstance(trusted_list, string_types): - trusted_list = [trusted_list] - - def _normalize(hostname): - if ":" in hostname: - hostname = hostname.rsplit(":", 1)[0] - return _encode_idna(hostname) - - try: - hostname = _normalize(hostname) - except UnicodeError: - return False - for ref in trusted_list: - if ref.startswith("."): - ref = ref[1:] - suffix_match = True - else: - suffix_match = False - try: - ref = _normalize(ref) - except UnicodeError: - return False - if ref == hostname: - return True - if suffix_match and hostname.endswith(b"." + ref): - return True - return False - - -def get_host(environ, trusted_hosts=None): - """Return the host for the given WSGI environment. This first checks - the ``Host`` header. If it's not present, then ``SERVER_NAME`` and - ``SERVER_PORT`` are used. The host will only contain the port if it - is different than the standard port for the protocol. - - Optionally, verify that the host is trusted using - :func:`host_is_trusted` and raise a - :exc:`~werkzeug.exceptions.SecurityError` if it is not. - - :param environ: The WSGI environment to get the host from. - :param trusted_hosts: A list of trusted hosts. - :return: Host, with port if necessary. - :raise ~werkzeug.exceptions.SecurityError: If the host is not - trusted. - """ - if "HTTP_HOST" in environ: - rv = environ["HTTP_HOST"] - if environ["wsgi.url_scheme"] == "http" and rv.endswith(":80"): - rv = rv[:-3] - elif environ["wsgi.url_scheme"] == "https" and rv.endswith(":443"): - rv = rv[:-4] - else: - rv = environ["SERVER_NAME"] - if (environ["wsgi.url_scheme"], environ["SERVER_PORT"]) not in ( - ("https", "443"), - ("http", "80"), - ): - rv += ":" + environ["SERVER_PORT"] - if trusted_hosts is not None: - if not host_is_trusted(rv, trusted_hosts): - from .exceptions import SecurityError - - raise SecurityError('Host "%s" is not trusted' % rv) - return rv - - -def get_content_length(environ): - """Returns the content length from the WSGI environment as - integer. If it's not available or chunked transfer encoding is used, - ``None`` is returned. - - .. versionadded:: 0.9 - - :param environ: the WSGI environ to fetch the content length from. - """ - if environ.get("HTTP_TRANSFER_ENCODING", "") == "chunked": - return None - - content_length = environ.get("CONTENT_LENGTH") - if content_length is not None: - try: - return max(0, int(content_length)) - except (ValueError, TypeError): - pass - - -def get_input_stream(environ, safe_fallback=True): - """Returns the input stream from the WSGI environment and wraps it - in the most sensible way possible. The stream returned is not the - raw WSGI stream in most cases but one that is safe to read from - without taking into account the content length. - - If content length is not set, the stream will be empty for safety reasons. - If the WSGI server supports chunked or infinite streams, it should set - the ``wsgi.input_terminated`` value in the WSGI environ to indicate that. - - .. versionadded:: 0.9 - - :param environ: the WSGI environ to fetch the stream from. - :param safe_fallback: use an empty stream as a safe fallback when the - content length is not set. Disabling this allows infinite streams, - which can be a denial-of-service risk. - """ - stream = environ["wsgi.input"] - content_length = get_content_length(environ) - - # A wsgi extension that tells us if the input is terminated. In - # that case we return the stream unchanged as we know we can safely - # read it until the end. - if environ.get("wsgi.input_terminated"): - return stream - - # If the request doesn't specify a content length, returning the stream is - # potentially dangerous because it could be infinite, malicious or not. If - # safe_fallback is true, return an empty stream instead for safety. - if content_length is None: - return BytesIO() if safe_fallback else stream - - # Otherwise limit the stream to the content length - return LimitedStream(stream, content_length) - - -def get_query_string(environ): - """Returns the `QUERY_STRING` from the WSGI environment. This also takes - care about the WSGI decoding dance on Python 3 environments as a - native string. The string returned will be restricted to ASCII - characters. - - .. versionadded:: 0.9 - - :param environ: the WSGI environment object to get the query string from. - """ - qs = wsgi_get_bytes(environ.get("QUERY_STRING", "")) - # QUERY_STRING really should be ascii safe but some browsers - # will send us some unicode stuff (I am looking at you IE). - # In that case we want to urllib quote it badly. - return try_coerce_native(url_quote(qs, safe=":&%=+$!*'(),")) - - -def get_path_info(environ, charset="utf-8", errors="replace"): - """Returns the `PATH_INFO` from the WSGI environment and properly - decodes it. This also takes care about the WSGI decoding dance - on Python 3 environments. if the `charset` is set to `None` a - bytestring is returned. - - .. versionadded:: 0.9 - - :param environ: the WSGI environment object to get the path from. - :param charset: the charset for the path info, or `None` if no - decoding should be performed. - :param errors: the decoding error handling. - """ - path = wsgi_get_bytes(environ.get("PATH_INFO", "")) - return to_unicode(path, charset, errors, allow_none_charset=True) - - -def get_script_name(environ, charset="utf-8", errors="replace"): - """Returns the `SCRIPT_NAME` from the WSGI environment and properly - decodes it. This also takes care about the WSGI decoding dance - on Python 3 environments. if the `charset` is set to `None` a - bytestring is returned. - - .. versionadded:: 0.9 - - :param environ: the WSGI environment object to get the path from. - :param charset: the charset for the path, or `None` if no - decoding should be performed. - :param errors: the decoding error handling. - """ - path = wsgi_get_bytes(environ.get("SCRIPT_NAME", "")) - return to_unicode(path, charset, errors, allow_none_charset=True) - - -def pop_path_info(environ, charset="utf-8", errors="replace"): - """Removes and returns the next segment of `PATH_INFO`, pushing it onto - `SCRIPT_NAME`. Returns `None` if there is nothing left on `PATH_INFO`. - - If the `charset` is set to `None` a bytestring is returned. - - If there are empty segments (``'/foo//bar``) these are ignored but - properly pushed to the `SCRIPT_NAME`: - - >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} - >>> pop_path_info(env) - 'a' - >>> env['SCRIPT_NAME'] - '/foo/a' - >>> pop_path_info(env) - 'b' - >>> env['SCRIPT_NAME'] - '/foo/a/b' - - .. versionadded:: 0.5 - - .. versionchanged:: 0.9 - The path is now decoded and a charset and encoding - parameter can be provided. - - :param environ: the WSGI environment that is modified. - """ - path = environ.get("PATH_INFO") - if not path: - return None - - script_name = environ.get("SCRIPT_NAME", "") - - # shift multiple leading slashes over - old_path = path - path = path.lstrip("/") - if path != old_path: - script_name += "/" * (len(old_path) - len(path)) - - if "/" not in path: - environ["PATH_INFO"] = "" - environ["SCRIPT_NAME"] = script_name + path - rv = wsgi_get_bytes(path) - else: - segment, path = path.split("/", 1) - environ["PATH_INFO"] = "/" + path - environ["SCRIPT_NAME"] = script_name + segment - rv = wsgi_get_bytes(segment) - - return to_unicode(rv, charset, errors, allow_none_charset=True) - - -def peek_path_info(environ, charset="utf-8", errors="replace"): - """Returns the next segment on the `PATH_INFO` or `None` if there - is none. Works like :func:`pop_path_info` without modifying the - environment: - - >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} - >>> peek_path_info(env) - 'a' - >>> peek_path_info(env) - 'a' - - If the `charset` is set to `None` a bytestring is returned. - - .. versionadded:: 0.5 - - .. versionchanged:: 0.9 - The path is now decoded and a charset and encoding - parameter can be provided. - - :param environ: the WSGI environment that is checked. - """ - segments = environ.get("PATH_INFO", "").lstrip("/").split("/", 1) - if segments: - return to_unicode( - wsgi_get_bytes(segments[0]), charset, errors, allow_none_charset=True - ) - - -def extract_path_info( - environ_or_baseurl, - path_or_url, - charset="utf-8", - errors="werkzeug.url_quote", - collapse_http_schemes=True, -): - """Extracts the path info from the given URL (or WSGI environment) and - path. The path info returned is a unicode string, not a bytestring - suitable for a WSGI environment. The URLs might also be IRIs. - - If the path info could not be determined, `None` is returned. - - Some examples: - - >>> extract_path_info('http://example.com/app', '/app/hello') - u'/hello' - >>> extract_path_info('http://example.com/app', - ... 'https://example.com/app/hello') - u'/hello' - >>> extract_path_info('http://example.com/app', - ... 'https://example.com/app/hello', - ... collapse_http_schemes=False) is None - True - - Instead of providing a base URL you can also pass a WSGI environment. - - :param environ_or_baseurl: a WSGI environment dict, a base URL or - base IRI. This is the root of the - application. - :param path_or_url: an absolute path from the server root, a - relative path (in which case it's the path info) - or a full URL. Also accepts IRIs and unicode - parameters. - :param charset: the charset for byte data in URLs - :param errors: the error handling on decode - :param collapse_http_schemes: if set to `False` the algorithm does - not assume that http and https on the - same server point to the same - resource. - - .. versionchanged:: 0.15 - The ``errors`` parameter defaults to leaving invalid bytes - quoted instead of replacing them. - - .. versionadded:: 0.6 - """ - - def _normalize_netloc(scheme, netloc): - parts = netloc.split(u"@", 1)[-1].split(u":", 1) - if len(parts) == 2: - netloc, port = parts - if (scheme == u"http" and port == u"80") or ( - scheme == u"https" and port == u"443" - ): - port = None - else: - netloc = parts[0] - port = None - if port is not None: - netloc += u":" + port - return netloc - - # make sure whatever we are working on is a IRI and parse it - path = uri_to_iri(path_or_url, charset, errors) - if isinstance(environ_or_baseurl, dict): - environ_or_baseurl = get_current_url(environ_or_baseurl, root_only=True) - base_iri = uri_to_iri(environ_or_baseurl, charset, errors) - base_scheme, base_netloc, base_path = url_parse(base_iri)[:3] - cur_scheme, cur_netloc, cur_path, = url_parse(url_join(base_iri, path))[:3] - - # normalize the network location - base_netloc = _normalize_netloc(base_scheme, base_netloc) - cur_netloc = _normalize_netloc(cur_scheme, cur_netloc) - - # is that IRI even on a known HTTP scheme? - if collapse_http_schemes: - for scheme in base_scheme, cur_scheme: - if scheme not in (u"http", u"https"): - return None - else: - if not (base_scheme in (u"http", u"https") and base_scheme == cur_scheme): - return None - - # are the netlocs compatible? - if base_netloc != cur_netloc: - return None - - # are we below the application path? - base_path = base_path.rstrip(u"/") - if not cur_path.startswith(base_path): - return None - - return u"/" + cur_path[len(base_path) :].lstrip(u"/") - - -@implements_iterator -class ClosingIterator(object): - """The WSGI specification requires that all middlewares and gateways - respect the `close` callback of the iterable returned by the application. - Because it is useful to add another close action to a returned iterable - and adding a custom iterable is a boring task this class can be used for - that:: - - return ClosingIterator(app(environ, start_response), [cleanup_session, - cleanup_locals]) - - If there is just one close function it can be passed instead of the list. - - A closing iterator is not needed if the application uses response objects - and finishes the processing if the response is started:: - - try: - return response(environ, start_response) - finally: - cleanup_session() - cleanup_locals() - """ - - def __init__(self, iterable, callbacks=None): - iterator = iter(iterable) - self._next = partial(next, iterator) - if callbacks is None: - callbacks = [] - elif callable(callbacks): - callbacks = [callbacks] - else: - callbacks = list(callbacks) - iterable_close = getattr(iterable, "close", None) - if iterable_close: - callbacks.insert(0, iterable_close) - self._callbacks = callbacks - - def __iter__(self): - return self - - def __next__(self): - return self._next() - - def close(self): - for callback in self._callbacks: - callback() - - -def wrap_file(environ, file, buffer_size=8192): - """Wraps a file. This uses the WSGI server's file wrapper if available - or otherwise the generic :class:`FileWrapper`. - - .. versionadded:: 0.5 - - If the file wrapper from the WSGI server is used it's important to not - iterate over it from inside the application but to pass it through - unchanged. If you want to pass out a file wrapper inside a response - object you have to set :attr:`~BaseResponse.direct_passthrough` to `True`. - - More information about file wrappers are available in :pep:`333`. - - :param file: a :class:`file`-like object with a :meth:`~file.read` method. - :param buffer_size: number of bytes for one iteration. - """ - return environ.get("wsgi.file_wrapper", FileWrapper)(file, buffer_size) - - -@implements_iterator -class FileWrapper(object): - """This class can be used to convert a :class:`file`-like object into - an iterable. It yields `buffer_size` blocks until the file is fully - read. - - You should not use this class directly but rather use the - :func:`wrap_file` function that uses the WSGI server's file wrapper - support if it's available. - - .. versionadded:: 0.5 - - If you're using this object together with a :class:`BaseResponse` you have - to use the `direct_passthrough` mode. - - :param file: a :class:`file`-like object with a :meth:`~file.read` method. - :param buffer_size: number of bytes for one iteration. - """ - - def __init__(self, file, buffer_size=8192): - self.file = file - self.buffer_size = buffer_size - - def close(self): - if hasattr(self.file, "close"): - self.file.close() - - def seekable(self): - if hasattr(self.file, "seekable"): - return self.file.seekable() - if hasattr(self.file, "seek"): - return True - return False - - def seek(self, *args): - if hasattr(self.file, "seek"): - self.file.seek(*args) - - def tell(self): - if hasattr(self.file, "tell"): - return self.file.tell() - return None - - def __iter__(self): - return self - - def __next__(self): - data = self.file.read(self.buffer_size) - if data: - return data - raise StopIteration() - - -@implements_iterator -class _RangeWrapper(object): - # private for now, but should we make it public in the future ? - - """This class can be used to convert an iterable object into - an iterable that will only yield a piece of the underlying content. - It yields blocks until the underlying stream range is fully read. - The yielded blocks will have a size that can't exceed the original - iterator defined block size, but that can be smaller. - - If you're using this object together with a :class:`BaseResponse` you have - to use the `direct_passthrough` mode. - - :param iterable: an iterable object with a :meth:`__next__` method. - :param start_byte: byte from which read will start. - :param byte_range: how many bytes to read. - """ - - def __init__(self, iterable, start_byte=0, byte_range=None): - self.iterable = iter(iterable) - self.byte_range = byte_range - self.start_byte = start_byte - self.end_byte = None - if byte_range is not None: - self.end_byte = self.start_byte + self.byte_range - self.read_length = 0 - self.seekable = hasattr(iterable, "seekable") and iterable.seekable() - self.end_reached = False - - def __iter__(self): - return self - - def _next_chunk(self): - try: - chunk = next(self.iterable) - self.read_length += len(chunk) - return chunk - except StopIteration: - self.end_reached = True - raise - - def _first_iteration(self): - chunk = None - if self.seekable: - self.iterable.seek(self.start_byte) - self.read_length = self.iterable.tell() - contextual_read_length = self.read_length - else: - while self.read_length <= self.start_byte: - chunk = self._next_chunk() - if chunk is not None: - chunk = chunk[self.start_byte - self.read_length :] - contextual_read_length = self.start_byte - return chunk, contextual_read_length - - def _next(self): - if self.end_reached: - raise StopIteration() - chunk = None - contextual_read_length = self.read_length - if self.read_length == 0: - chunk, contextual_read_length = self._first_iteration() - if chunk is None: - chunk = self._next_chunk() - if self.end_byte is not None and self.read_length >= self.end_byte: - self.end_reached = True - return chunk[: self.end_byte - contextual_read_length] - return chunk - - def __next__(self): - chunk = self._next() - if chunk: - return chunk - self.end_reached = True - raise StopIteration() - - def close(self): - if hasattr(self.iterable, "close"): - self.iterable.close() - - -def _make_chunk_iter(stream, limit, buffer_size): - """Helper for the line and chunk iter functions.""" - if isinstance(stream, (bytes, bytearray, text_type)): - raise TypeError( - "Passed a string or byte object instead of true iterator or stream." - ) - if not hasattr(stream, "read"): - for item in stream: - if item: - yield item - return - if not isinstance(stream, LimitedStream) and limit is not None: - stream = LimitedStream(stream, limit) - _read = stream.read - while 1: - item = _read(buffer_size) - if not item: - break - yield item - - -def make_line_iter(stream, limit=None, buffer_size=10 * 1024, cap_at_buffer=False): - """Safely iterates line-based over an input stream. If the input stream - is not a :class:`LimitedStream` the `limit` parameter is mandatory. - - This uses the stream's :meth:`~file.read` method internally as opposite - to the :meth:`~file.readline` method that is unsafe and can only be used - in violation of the WSGI specification. The same problem applies to the - `__iter__` function of the input stream which calls :meth:`~file.readline` - without arguments. - - If you need line-by-line processing it's strongly recommended to iterate - over the input stream using this helper function. - - .. versionchanged:: 0.8 - This function now ensures that the limit was reached. - - .. versionadded:: 0.9 - added support for iterators as input stream. - - .. versionadded:: 0.11.10 - added support for the `cap_at_buffer` parameter. - - :param stream: the stream or iterate to iterate over. - :param limit: the limit in bytes for the stream. (Usually - content length. Not necessary if the `stream` - is a :class:`LimitedStream`. - :param buffer_size: The optional buffer size. - :param cap_at_buffer: if this is set chunks are split if they are longer - than the buffer size. Internally this is implemented - that the buffer size might be exhausted by a factor - of two however. - """ - _iter = _make_chunk_iter(stream, limit, buffer_size) - - first_item = next(_iter, "") - if not first_item: - return - - s = make_literal_wrapper(first_item) - empty = s("") - cr = s("\r") - lf = s("\n") - crlf = s("\r\n") - - _iter = chain((first_item,), _iter) - - def _iter_basic_lines(): - _join = empty.join - buffer = [] - while 1: - new_data = next(_iter, "") - if not new_data: - break - new_buf = [] - buf_size = 0 - for item in chain(buffer, new_data.splitlines(True)): - new_buf.append(item) - buf_size += len(item) - if item and item[-1:] in crlf: - yield _join(new_buf) - new_buf = [] - elif cap_at_buffer and buf_size >= buffer_size: - rv = _join(new_buf) - while len(rv) >= buffer_size: - yield rv[:buffer_size] - rv = rv[buffer_size:] - new_buf = [rv] - buffer = new_buf - if buffer: - yield _join(buffer) - - # This hackery is necessary to merge 'foo\r' and '\n' into one item - # of 'foo\r\n' if we were unlucky and we hit a chunk boundary. - previous = empty - for item in _iter_basic_lines(): - if item == lf and previous[-1:] == cr: - previous += item - item = empty - if previous: - yield previous - previous = item - if previous: - yield previous - - -def make_chunk_iter( - stream, separator, limit=None, buffer_size=10 * 1024, cap_at_buffer=False -): - """Works like :func:`make_line_iter` but accepts a separator - which divides chunks. If you want newline based processing - you should use :func:`make_line_iter` instead as it - supports arbitrary newline markers. - - .. versionadded:: 0.8 - - .. versionadded:: 0.9 - added support for iterators as input stream. - - .. versionadded:: 0.11.10 - added support for the `cap_at_buffer` parameter. - - :param stream: the stream or iterate to iterate over. - :param separator: the separator that divides chunks. - :param limit: the limit in bytes for the stream. (Usually - content length. Not necessary if the `stream` - is otherwise already limited). - :param buffer_size: The optional buffer size. - :param cap_at_buffer: if this is set chunks are split if they are longer - than the buffer size. Internally this is implemented - that the buffer size might be exhausted by a factor - of two however. - """ - _iter = _make_chunk_iter(stream, limit, buffer_size) - - first_item = next(_iter, "") - if not first_item: - return - - _iter = chain((first_item,), _iter) - if isinstance(first_item, text_type): - separator = to_unicode(separator) - _split = re.compile(r"(%s)" % re.escape(separator)).split - _join = u"".join - else: - separator = to_bytes(separator) - _split = re.compile(b"(" + re.escape(separator) + b")").split - _join = b"".join - - buffer = [] - while 1: - new_data = next(_iter, "") - if not new_data: - break - chunks = _split(new_data) - new_buf = [] - buf_size = 0 - for item in chain(buffer, chunks): - if item == separator: - yield _join(new_buf) - new_buf = [] - buf_size = 0 - else: - buf_size += len(item) - new_buf.append(item) - - if cap_at_buffer and buf_size >= buffer_size: - rv = _join(new_buf) - while len(rv) >= buffer_size: - yield rv[:buffer_size] - rv = rv[buffer_size:] - new_buf = [rv] - buf_size = len(rv) - - buffer = new_buf - if buffer: - yield _join(buffer) - - -@implements_iterator -class LimitedStream(io.IOBase): - """Wraps a stream so that it doesn't read more than n bytes. If the - stream is exhausted and the caller tries to get more bytes from it - :func:`on_exhausted` is called which by default returns an empty - string. The return value of that function is forwarded - to the reader function. So if it returns an empty string - :meth:`read` will return an empty string as well. - - The limit however must never be higher than what the stream can - output. Otherwise :meth:`readlines` will try to read past the - limit. - - .. admonition:: Note on WSGI compliance - - calls to :meth:`readline` and :meth:`readlines` are not - WSGI compliant because it passes a size argument to the - readline methods. Unfortunately the WSGI PEP is not safely - implementable without a size argument to :meth:`readline` - because there is no EOF marker in the stream. As a result - of that the use of :meth:`readline` is discouraged. - - For the same reason iterating over the :class:`LimitedStream` - is not portable. It internally calls :meth:`readline`. - - We strongly suggest using :meth:`read` only or using the - :func:`make_line_iter` which safely iterates line-based - over a WSGI input stream. - - :param stream: the stream to wrap. - :param limit: the limit for the stream, must not be longer than - what the string can provide if the stream does not - end with `EOF` (like `wsgi.input`) - """ - - def __init__(self, stream, limit): - self._read = stream.read - self._readline = stream.readline - self._pos = 0 - self.limit = limit - - def __iter__(self): - return self - - @property - def is_exhausted(self): - """If the stream is exhausted this attribute is `True`.""" - return self._pos >= self.limit - - def on_exhausted(self): - """This is called when the stream tries to read past the limit. - The return value of this function is returned from the reading - function. - """ - # Read null bytes from the stream so that we get the - # correct end of stream marker. - return self._read(0) - - def on_disconnect(self): - """What should happen if a disconnect is detected? The return - value of this function is returned from read functions in case - the client went away. By default a - :exc:`~werkzeug.exceptions.ClientDisconnected` exception is raised. - """ - from .exceptions import ClientDisconnected - - raise ClientDisconnected() - - def exhaust(self, chunk_size=1024 * 64): - """Exhaust the stream. This consumes all the data left until the - limit is reached. - - :param chunk_size: the size for a chunk. It will read the chunk - until the stream is exhausted and throw away - the results. - """ - to_read = self.limit - self._pos - chunk = chunk_size - while to_read > 0: - chunk = min(to_read, chunk) - self.read(chunk) - to_read -= chunk - - def read(self, size=None): - """Read `size` bytes or if size is not provided everything is read. - - :param size: the number of bytes read. - """ - if self._pos >= self.limit: - return self.on_exhausted() - if size is None or size == -1: # -1 is for consistence with file - size = self.limit - to_read = min(self.limit - self._pos, size) - try: - read = self._read(to_read) - except (IOError, ValueError): - return self.on_disconnect() - if to_read and len(read) != to_read: - return self.on_disconnect() - self._pos += len(read) - return read - - def readline(self, size=None): - """Reads one line from the stream.""" - if self._pos >= self.limit: - return self.on_exhausted() - if size is None: - size = self.limit - self._pos - else: - size = min(size, self.limit - self._pos) - try: - line = self._readline(size) - except (ValueError, IOError): - return self.on_disconnect() - if size and not line: - return self.on_disconnect() - self._pos += len(line) - return line - - def readlines(self, size=None): - """Reads a file into a list of strings. It calls :meth:`readline` - until the file is read to the end. It does support the optional - `size` argument if the underlying stream supports it for - `readline`. - """ - last_pos = self._pos - result = [] - if size is not None: - end = min(self.limit, last_pos + size) - else: - end = self.limit - while 1: - if size is not None: - size -= last_pos - self._pos - if self._pos >= end: - break - result.append(self.readline(size)) - if size is not None: - last_pos = self._pos - return result - - def tell(self): - """Returns the position of the stream. - - .. versionadded:: 0.9 - """ - return self._pos - - def __next__(self): - line = self.readline() - if not line: - raise StopIteration() - return line - - def readable(self): - return True diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/INSTALLER b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/LICENSE.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/LICENSE.txt deleted file mode 100644 index c3441e6..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -"wheel" copyright (c) 2012-2014 Daniel Holth and -contributors. - -The MIT License - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/METADATA b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/METADATA deleted file mode 100644 index 8395321..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/METADATA +++ /dev/null @@ -1,66 +0,0 @@ -Metadata-Version: 2.1 -Name: wheel -Version: 0.34.2 -Summary: A built-package format for Python -Home-page: https://github.com/pypa/wheel -Author: Daniel Holth -Author-email: dholth@fastmail.fm -Maintainer: Alex Grönholm -Maintainer-email: alex.gronholm@nextday.fi -License: MIT -Project-URL: Documentation, https://wheel.readthedocs.io/ -Project-URL: Changelog, https://wheel.readthedocs.io/en/stable/news.html -Project-URL: Issue Tracker, https://github.com/pypa/wheel/issues -Keywords: wheel,packaging -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* -Provides-Extra: test -Requires-Dist: pytest (>=3.0.0) ; extra == 'test' -Requires-Dist: pytest-cov ; extra == 'test' - -wheel -===== - -This library is the reference implementation of the Python wheel packaging -standard, as defined in `PEP 427`_. - -It has two different roles: - -#. A setuptools_ extension for building wheels that provides the - ``bdist_wheel`` setuptools command -#. A command line tool for working with wheel files - -It should be noted that wheel is **not** intended to be used as a library, and -as such there is no stable, public API. - -.. _PEP 427: https://www.python.org/dev/peps/pep-0427/ -.. _setuptools: https://pypi.org/project/setuptools/ - -Documentation -------------- - -The documentation_ can be found on Read The Docs. - -.. _documentation: https://wheel.readthedocs.io/ - -Code of Conduct ---------------- - -Everyone interacting in the wheel project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. - -.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ - - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/RECORD b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/RECORD deleted file mode 100644 index 2a4d41d..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/RECORD +++ /dev/null @@ -1,38 +0,0 @@ -../../../bin/wheel,sha256=DNu5BBHOD0OJGAqEfY2fnUCmhQW3ppprsGAqqh-mBog,271 -wheel-0.34.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -wheel-0.34.2.dist-info/LICENSE.txt,sha256=zKniDGrx_Pv2lAjzd3aShsvuvN7TNhAMm0o_NfvmNeQ,1125 -wheel-0.34.2.dist-info/METADATA,sha256=uizJLqT4WTszpXZTkDAoUn364lfXXMz-ha1TLIuQQbU,2219 -wheel-0.34.2.dist-info/RECORD,, -wheel-0.34.2.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 -wheel-0.34.2.dist-info/entry_points.txt,sha256=N8HbYFST3yrNQYeB2wXWBEPUhFsEtKNRPaCFGJPyqyc,108 -wheel-0.34.2.dist-info/top_level.txt,sha256=HxSBIbgEstMPe4eFawhA66Mq-QYHMopXVoAncfjb_1c,6 -wheel/__init__.py,sha256=HnvQS9U0JqVi8rcO-9DbcHRmVtnblu7VwdzoKbMiZDQ,23 -wheel/__main__.py,sha256=lF-YLO4hdQmoWuh4eWZd8YL1U95RSdm76sNLBXa0vjE,417 -wheel/__pycache__/__init__.cpython-37.pyc,, -wheel/__pycache__/__main__.cpython-37.pyc,, -wheel/__pycache__/_version.cpython-37.pyc,, -wheel/__pycache__/bdist_wheel.cpython-37.pyc,, -wheel/__pycache__/macosx_libfile.cpython-37.pyc,, -wheel/__pycache__/metadata.cpython-37.pyc,, -wheel/__pycache__/pep425tags.cpython-37.pyc,, -wheel/__pycache__/pkginfo.cpython-37.pyc,, -wheel/__pycache__/util.cpython-37.pyc,, -wheel/__pycache__/wheelfile.cpython-37.pyc,, -wheel/_version.py,sha256=KiDEywHVTrXNxe6ojGe-7gEm6gUYge5r_fThX1den7Y,133 -wheel/bdist_wheel.py,sha256=fgVFnJ2cC3MkU5Wy0nNLCzbJoGorSzSrzM9PFq4HWj0,15840 -wheel/cli/__init__.py,sha256=GWSoGUpRabTf8bk3FsNTPrc5Fsr8YOv2dX55iY2W7eY,2572 -wheel/cli/__pycache__/__init__.cpython-37.pyc,, -wheel/cli/__pycache__/convert.cpython-37.pyc,, -wheel/cli/__pycache__/install.cpython-37.pyc,, -wheel/cli/__pycache__/pack.cpython-37.pyc,, -wheel/cli/__pycache__/unpack.cpython-37.pyc,, -wheel/cli/convert.py,sha256=7F4vj23A2OghDDWn9gX2V-_TeXMza1a5nIejmFGEUJM,9498 -wheel/cli/install.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -wheel/cli/pack.py,sha256=S-J1iIy1GPDTTDdn-_SwxGa7N729h4iZNI11EDFCqfA,3208 -wheel/cli/unpack.py,sha256=0VWzT7U_xyenTPwEVavxqvdee93GPvAFHnR3Uu91aRc,673 -wheel/macosx_libfile.py,sha256=NhNz1C3zF_78iMUd4ij0le1jVJNnz93tCAICSKXgYvg,11858 -wheel/metadata.py,sha256=siS-hs_DTT0ScpbzloYbQSGYXUDC_Tim10ixcYWSM-4,4517 -wheel/pep425tags.py,sha256=tuXvpyhYJHDcsXHgSRonny1X3kG3TSn7CN9nL9tZUMA,9071 -wheel/pkginfo.py,sha256=GR76kupQzn1x9sKDaXuE6B6FsZ4OkfRtG7pndlXPvQ4,1257 -wheel/util.py,sha256=mnNZkJCi9DHLI_q4lTudoD0mW97h_AoAWl7prNPLXJc,938 -wheel/wheelfile.py,sha256=WsWfD-OBgHxxeF7SxRi3OX6l_qxtP06b2ZK0NVhT_n0,7298 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/WHEEL b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/WHEEL deleted file mode 100644 index ef99c6c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/entry_points.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/entry_points.txt deleted file mode 100644 index b27acad..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/entry_points.txt +++ /dev/null @@ -1,6 +0,0 @@ -[console_scripts] -wheel = wheel.cli:main - -[distutils.commands] -bdist_wheel = wheel.bdist_wheel:bdist_wheel - diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/top_level.txt b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/top_level.txt deleted file mode 100644 index 2309722..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel-0.34.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -wheel diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__init__.py deleted file mode 100644 index 3c92ca2..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '0.34.2' diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__main__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__main__.py deleted file mode 100644 index b3773a2..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Wheel command line tool (enable python -m wheel syntax) -""" - -import sys - - -def main(): # needed for console script - if __package__ == '': - # To be able to run 'python wheel-0.9.whl/wheel': - import os.path - path = os.path.dirname(os.path.dirname(__file__)) - sys.path[0:0] = [path] - import wheel.cli - sys.exit(wheel.cli.main()) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 514432be2c914d0d1ca931ba75834e1b8a257b04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmZ?b<>g`kf*i(~apFMwF^B^Lj6jA15EpX*i4=w?h7`tN22G|aHUm9l6Fnn8O~zZ? z@$qG;Ma7xbB0nU`4-AFo$Xd5gm)H$SB`C)EyQ?`I%p005?bCiwsW diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__main__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/__main__.cpython-37.pyc deleted file mode 100644 index da9a7ab0622fbdde2fe690b2842b23b386530855..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 551 zcmYk2!EO^V5QaVWZsTkzaNq&<*p)~kBrZr5Lgii|aX`ue%dAb~)Vp4-4K!790v>`} z_Q)&w+EZVlr;ay(7-@ca#=kwEeSUIM5DW{yJ`O<0Z7Ti-!^Im+{~Se;B~hTLg(WDa zvL9qgHBWISuZj;Vt!-Jmrje~Gt!Z@`oU`SrZsjMd%We}^ zt}SOx`E7LiO&jEORovk)a#1Huksxx+x0wDNN|hI* z5b`xe5B*8c5DL9VI~wx+WJ}k4KOGLR1Yy}lBt5>JR7E@%qLcNNywpO(iSzSLhE>c) zohZ|{veA(X@!8nqV1DD5(~*B(TN5*VZ9-(@vXQ2(SftMPi9hC}?KkNkV|D*x5t?q% znQmrUAEdRjug-Zb?R#DDSx%gE0fr@mPII{mp%M>EP9FE~5^d!LEa diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/_version.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/_version.cpython-37.pyc deleted file mode 100644 index baa80dac3c0b04a3f22578be0170c39c3d8bc3d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmZ?b<>g`kf*i(~ajii5F^B^Lj6jA15EpX*i4=w?h7`tN22G|aF#|ngV?8syg8bqV zVamct5;BYi^C>2KczG$)s6*d%4Z;E006R{D;EF& diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/bdist_wheel.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/bdist_wheel.cpython-37.pyc deleted file mode 100644 index 9d197c03dfc53c4cef1fae335be2edef16e5a512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10804 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 S8di3W7YpXDVy<||Jo0Y^e=h+5 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/metadata.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/metadata.cpython-37.pyc deleted file mode 100644 index 2c5f47ec210339b0405e4c1e019f74c21a37541e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3698 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pep425tags.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pep425tags.cpython-37.pyc deleted file mode 100644 index b9455a58ad87ee763d7d907223f0a7d50199619c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7510 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pkginfo.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/pkginfo.cpython-37.pyc deleted file mode 100644 index 3c757660cecab3f900b46c89949e8d8cbc766e2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1529 zcmb_c&yO256t+DxnMpRu(pHpG2{b|oDH6Mj1V@C}mTrX*VSz|(bLilWy~(umOV3`? zt+J=~&`ZUc8$I$b`O2yP0w><{BwOtQ;({aFZ=PT5@A>Arh>E6z79B3!8E+bsv9BG(c>O`#u@!oI1L}LO5A5UG(X|L zqM}pA(->DeDt^wUiAq!#=dS9hEu4GRhZxnzsIBQ1Mh(_c!*$el8>Qa*k&UiAolNSw zFzIm(DQKzkYM#nUrAx>y*@xfU-T8Wa@Ljr>etT!K|JD9vKV9Z_QJ>g!CILfw@`yg{ zLZ`Z#)wILzYs`_2xa%BBFd7afXm{`GN`tgD%s4G$qdCBS8@uV_VA(VF8(*#=z} z&#U8lw>fp!D9;QX8F@0l-!>tjvls_r>Kr1$>tgp1KSIN@6;k(1{Bre-TaIwWiofD# z;vSOvJ^O*(XDfl=#n^Ee1um=`UA0+6J`3_S(k@)QKo}Z~i%V^coNJ#?JH&X98(hG7 z6u)6NVt9} zt9hZbW2noFzMiyD3tf!@Ac+GV=;Gr-TI-!e9t_Eul-f!qt-PGhkR+wg@BJMNHdrJ+ zA9x#QBzJg=$o;!e=s1e?EWD4#iaqiLq=J{?A`kxd!?BB`ndQ0LHYWh}Tw1NoOg0+R zOExlf9gS;XkdltlC|&J|0y+s3jc|ei4V2iWbi7L5L;sqSA+qw%qWKtuS~}Jwg#RI( zXbhw{pc{f4IA9sPOZH8&*8~vru+=*J<^L;C63PeIjenbXhYQ|A0sWua5zC{Ec;E^F zBe8CfUMI)3*6~Ir0lpcRuhfeG1J7kK9`#+EWvZTKs6$=Kyx8?c1Z_pdCsj_gO~dT) z!Kbb}mZiQ!l)CLUc)odZykI?NzHq$Wz$2rQx&*`}pO>{dDfAa~%ZBt8ioOs$ diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/util.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/util.cpython-37.pyc deleted file mode 100644 index edc08b94cde7841c80cdd244897f5187988fe860..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1274 zcmb_aF;Cnu6th zW+bUSO{j}m!UQ|@I9VZ_eI{y4G!kFX(;#W`dEVguHBG|2Ct5DsgzN$j>MU>a@R}qM zZ}ABH9G~ND@NM4VUGN=F4@kUt2Pc!gJ4ABtkIYg3-H>4l7JAHogsqps7*Y{KubApp zlY_NWDj;^WcIck+aOPkJQs6_Cjdie1dqb_A3>`I)LQ>=Y=pJ} z7d2MZgsckDAk5m}6x~rhczJaEkV1?L{e-Rs2n@NQ6}hE1j614gcKK?gGMyfY!Qtjc z&CKeBG$+N#td=R~K+P{~^B(974pS{QH|*k*5*sLOlq_Rv8$31XEJ!^21#ImG$rQ#D zl$gUyyP>{@7fw0D!Cq1BZIflvBVVZj%oVBV5}=3iHl}dbEY0FpUFda(ofRGd7w|HX zt9f{zy26CxXZXc~ThGFO4j*2^*4T`&9#xo`Twsdkr>d-}cB*81m$jl}&&^r2p^xf- ziD^CJ>FL@i)q@A&zJb3U4OuPy9|*Q(#1}I#<5DP8@Lzz00K{o>Z3f0lU4t@%Qs=rg z$4nO1(_?Mh=R#>&70QP{6|!WTJ1FwqeH$Ktc=F@jeWzw9GRjHB(d;g&@R&zq maWtX+ZMbz-@KGi{;1o29ETr&wUD{v)Yx`)UAoRl^41NQ%0RKb) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/wheelfile.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/__pycache__/wheelfile.cpython-37.pyc deleted file mode 100644 index 1d059f3f54e055586dfbe22eaf8e2118af38474c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5470 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 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/_version.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/_version.py deleted file mode 100644 index 5f581f7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/_version.py +++ /dev/null @@ -1,4 +0,0 @@ -# coding: utf-8 -# file generated by setuptools_scm -# don't change, don't track in version control -version = '0.33.6.post32+gd3d7a43' diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py deleted file mode 100644 index 5cece1f..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py +++ /dev/null @@ -1,403 +0,0 @@ -""" -Create a wheel (.whl) distribution. - -A wheel is a built archive format. -""" - -import os -import shutil -import stat -import sys -import re -from collections import OrderedDict -from email.generator import Generator -from distutils.core import Command -from distutils.sysconfig import get_python_version -from distutils import log as logger -from glob import iglob -from shutil import rmtree -from warnings import warn -from zipfile import ZIP_DEFLATED, ZIP_STORED - -import pkg_resources - -from .pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag, get_platform -from .pkginfo import write_pkg_info -from .metadata import pkginfo_to_metadata -from .wheelfile import WheelFile -from . import pep425tags -from . import __version__ as wheel_version - - -safe_name = pkg_resources.safe_name -safe_version = pkg_resources.safe_version - -PY_LIMITED_API_PATTERN = r'cp3\d' - - -def safer_name(name): - return safe_name(name).replace('-', '_') - - -def safer_version(version): - return safe_version(version).replace('-', '_') - - -def remove_readonly(func, path, excinfo): - print(str(excinfo[1])) - os.chmod(path, stat.S_IWRITE) - func(path) - - -class bdist_wheel(Command): - - description = 'create a wheel distribution' - - supported_compressions = OrderedDict([ - ('stored', ZIP_STORED), - ('deflated', ZIP_DEFLATED) - ]) - - user_options = [('bdist-dir=', 'b', - "temporary directory for creating the distribution"), - ('plat-name=', 'p', - "platform name to embed in generated filenames " - "(default: %s)" % get_platform(None)), - ('keep-temp', 'k', - "keep the pseudo-installation tree around after " + - "creating the distribution archive"), - ('dist-dir=', 'd', - "directory to put final built distributions in"), - ('skip-build', None, - "skip rebuilding everything (for testing/debugging)"), - ('relative', None, - "build the archive using relative paths " - "(default: false)"), - ('owner=', 'u', - "Owner name used when creating a tar file" - " [default: current user]"), - ('group=', 'g', - "Group name used when creating a tar file" - " [default: current group]"), - ('universal', None, - "make a universal wheel" - " (default: false)"), - ('compression=', None, - "zipfile compression (one of: {})" - " (default: 'deflated')" - .format(', '.join(supported_compressions))), - ('python-tag=', None, - "Python implementation compatibility tag" - " (default: py%s)" % get_impl_ver()[0]), - ('build-number=', None, - "Build number for this particular version. " - "As specified in PEP-0427, this must start with a digit. " - "[default: None]"), - ('py-limited-api=', None, - "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" - " (default: false)"), - ] - - boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] - - def initialize_options(self): - self.bdist_dir = None - self.data_dir = None - self.plat_name = None - self.plat_tag = None - self.format = 'zip' - self.keep_temp = False - self.dist_dir = None - self.egginfo_dir = None - self.root_is_pure = None - self.skip_build = None - self.relative = False - self.owner = None - self.group = None - self.universal = False - self.compression = 'deflated' - self.python_tag = 'py' + get_impl_ver()[0] - self.build_number = None - self.py_limited_api = False - self.plat_name_supplied = False - - def finalize_options(self): - if self.bdist_dir is None: - bdist_base = self.get_finalized_command('bdist').bdist_base - self.bdist_dir = os.path.join(bdist_base, 'wheel') - - self.data_dir = self.wheel_dist_name + '.data' - self.plat_name_supplied = self.plat_name is not None - - try: - self.compression = self.supported_compressions[self.compression] - except KeyError: - raise ValueError('Unsupported compression: {}'.format(self.compression)) - - need_options = ('dist_dir', 'plat_name', 'skip_build') - - self.set_undefined_options('bdist', - *zip(need_options, need_options)) - - self.root_is_pure = not (self.distribution.has_ext_modules() - or self.distribution.has_c_libraries()) - - if self.py_limited_api and not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api): - raise ValueError("py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN) - - # Support legacy [wheel] section for setting universal - wheel = self.distribution.get_option_dict('wheel') - if 'universal' in wheel: - # please don't define this in your global configs - logger.warn('The [wheel] section is deprecated. Use [bdist_wheel] instead.') - val = wheel['universal'][1].strip() - if val.lower() in ('1', 'true', 'yes'): - self.universal = True - - if self.build_number is not None and not self.build_number[:1].isdigit(): - raise ValueError("Build tag (build-number) must start with a digit.") - - @property - def wheel_dist_name(self): - """Return distribution full name with - replaced with _""" - components = (safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) - if self.build_number: - components += (self.build_number,) - return '-'.join(components) - - def get_tag(self): - # bdist sets self.plat_name if unset, we should only use it for purepy - # wheels if the user supplied it. - if self.plat_name_supplied: - plat_name = self.plat_name - elif self.root_is_pure: - plat_name = 'any' - else: - # macosx contains system version in platform name so need special handle - if self.plat_name and not self.plat_name.startswith("macosx"): - plat_name = self.plat_name - else: - plat_name = get_platform(self.bdist_dir) - - if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: - plat_name = 'linux_i686' - - plat_name = plat_name.replace('-', '_').replace('.', '_') - - if self.root_is_pure: - if self.universal: - impl = 'py2.py3' - else: - impl = self.python_tag - tag = (impl, 'none', plat_name) - else: - impl_name = get_abbr_impl() - impl_ver = get_impl_ver() - impl = impl_name + impl_ver - # We don't work on CPython 3.1, 3.0. - if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): - impl = self.py_limited_api - abi_tag = 'abi3' - else: - abi_tag = str(get_abi_tag()).lower() - tag = (impl, abi_tag, plat_name) - supported_tags = pep425tags.get_supported( - self.bdist_dir, - supplied_platform=plat_name if self.plat_name_supplied else None) - # XXX switch to this alternate implementation for non-pure: - if not self.py_limited_api: - assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) - assert tag in supported_tags, "would build wheel with unsupported tag {}".format(tag) - return tag - - def run(self): - build_scripts = self.reinitialize_command('build_scripts') - build_scripts.executable = 'python' - build_scripts.force = True - - build_ext = self.reinitialize_command('build_ext') - build_ext.inplace = False - - if not self.skip_build: - self.run_command('build') - - install = self.reinitialize_command('install', - reinit_subcommands=True) - install.root = self.bdist_dir - install.compile = False - install.skip_build = self.skip_build - install.warn_dir = False - - # A wheel without setuptools scripts is more cross-platform. - # Use the (undocumented) `no_ep` option to setuptools' - # install_scripts command to avoid creating entry point scripts. - install_scripts = self.reinitialize_command('install_scripts') - install_scripts.no_ep = True - - # Use a custom scheme for the archive, because we have to decide - # at installation time which scheme to use. - for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): - setattr(install, - 'install_' + key, - os.path.join(self.data_dir, key)) - - basedir_observed = '' - - if os.name == 'nt': - # win32 barfs if any of these are ''; could be '.'? - # (distutils.command.install:change_roots bug) - basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..')) - self.install_libbase = self.install_lib = basedir_observed - - setattr(install, - 'install_purelib' if self.root_is_pure else 'install_platlib', - basedir_observed) - - logger.info("installing to %s", self.bdist_dir) - - self.run_command('install') - - impl_tag, abi_tag, plat_tag = self.get_tag() - archive_basename = "{}-{}-{}-{}".format(self.wheel_dist_name, impl_tag, abi_tag, plat_tag) - if not self.relative: - archive_root = self.bdist_dir - else: - archive_root = os.path.join( - self.bdist_dir, - self._ensure_relative(install.install_base)) - - self.set_undefined_options('install_egg_info', ('target', 'egginfo_dir')) - distinfo_dirname = '{}-{}.dist-info'.format( - safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) - distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) - self.egg2dist(self.egginfo_dir, distinfo_dir) - - self.write_wheelfile(distinfo_dir) - - # Make the archive - if not os.path.exists(self.dist_dir): - os.makedirs(self.dist_dir) - - wheel_path = os.path.join(self.dist_dir, archive_basename + '.whl') - with WheelFile(wheel_path, 'w', self.compression) as wf: - wf.write_files(archive_root) - - # Add to 'Distribution.dist_files' so that the "upload" command works - getattr(self.distribution, 'dist_files', []).append( - ('bdist_wheel', get_python_version(), wheel_path)) - - if not self.keep_temp: - logger.info('removing %s', self.bdist_dir) - if not self.dry_run: - rmtree(self.bdist_dir, onerror=remove_readonly) - - def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): - from email.message import Message - msg = Message() - msg['Wheel-Version'] = '1.0' # of the spec - msg['Generator'] = generator - msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() - if self.build_number is not None: - msg['Build'] = self.build_number - - # Doesn't work for bdist_wininst - impl_tag, abi_tag, plat_tag = self.get_tag() - for impl in impl_tag.split('.'): - for abi in abi_tag.split('.'): - for plat in plat_tag.split('.'): - msg['Tag'] = '-'.join((impl, abi, plat)) - - wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') - logger.info('creating %s', wheelfile_path) - with open(wheelfile_path, 'w') as f: - Generator(f, maxheaderlen=0).flatten(msg) - - def _ensure_relative(self, path): - # copied from dir_util, deleted - drive, path = os.path.splitdrive(path) - if path[0:1] == os.sep: - path = drive + path[1:] - return path - - @property - def license_paths(self): - metadata = self.distribution.get_option_dict('metadata') - files = set() - patterns = sorted({ - option for option in metadata.get('license_files', ('', ''))[1].split() - }) - - if 'license_file' in metadata: - warn('The "license_file" option is deprecated. Use "license_files" instead.', - DeprecationWarning) - files.add(metadata['license_file'][1]) - - if 'license_file' not in metadata and 'license_files' not in metadata: - patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') - - for pattern in patterns: - for path in iglob(pattern): - if path not in files and os.path.isfile(path): - logger.info('adding license file "%s" (matched pattern "%s")', path, pattern) - files.add(path) - - return files - - def egg2dist(self, egginfo_path, distinfo_path): - """Convert an .egg-info directory into a .dist-info directory""" - def adios(p): - """Appropriately delete directory, file or link.""" - if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): - shutil.rmtree(p) - elif os.path.exists(p): - os.unlink(p) - - adios(distinfo_path) - - if not os.path.exists(egginfo_path): - # There is no egg-info. This is probably because the egg-info - # file/directory is not named matching the distribution name used - # to name the archive file. Check for this case and report - # accordingly. - import glob - pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') - possible = glob.glob(pat) - err = "Egg metadata expected at %s but not found" % (egginfo_path,) - if possible: - alt = os.path.basename(possible[0]) - err += " (%s found - possible misnamed archive file?)" % (alt,) - - raise ValueError(err) - - if os.path.isfile(egginfo_path): - # .egg-info is a single file - pkginfo_path = egginfo_path - pkg_info = pkginfo_to_metadata(egginfo_path, egginfo_path) - os.mkdir(distinfo_path) - else: - # .egg-info is a directory - pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') - pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path) - - # ignore common egg metadata that is useless to wheel - shutil.copytree(egginfo_path, distinfo_path, - ignore=lambda x, y: {'PKG-INFO', 'requires.txt', 'SOURCES.txt', - 'not-zip-safe'} - ) - - # delete dependency_links if it is only whitespace - dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') - with open(dependency_links_path, 'r') as dependency_links_file: - dependency_links = dependency_links_file.read().strip() - if not dependency_links: - adios(dependency_links_path) - - write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) - - for license_path in self.license_paths: - filename = os.path.basename(license_path) - shutil.copy(license_path, os.path.join(distinfo_path, filename)) - - adios(egginfo_path) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__init__.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__init__.py deleted file mode 100644 index 95740bf..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__init__.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Wheel command-line utility. -""" - -from __future__ import print_function - -import argparse -import os -import sys - - -def require_pkgresources(name): - try: - import pkg_resources # noqa: F401 - except ImportError: - raise RuntimeError("'{0}' needs pkg_resources (part of setuptools).".format(name)) - - -class WheelError(Exception): - pass - - -def unpack_f(args): - from .unpack import unpack - unpack(args.wheelfile, args.dest) - - -def pack_f(args): - from .pack import pack - pack(args.directory, args.dest_dir, args.build_number) - - -def convert_f(args): - from .convert import convert - convert(args.files, args.dest_dir, args.verbose) - - -def version_f(args): - from .. import __version__ - print("wheel %s" % __version__) - - -def parser(): - p = argparse.ArgumentParser() - s = p.add_subparsers(help="commands") - - unpack_parser = s.add_parser('unpack', help='Unpack wheel') - unpack_parser.add_argument('--dest', '-d', help='Destination directory', - default='.') - unpack_parser.add_argument('wheelfile', help='Wheel file') - unpack_parser.set_defaults(func=unpack_f) - - repack_parser = s.add_parser('pack', help='Repack wheel') - repack_parser.add_argument('directory', help='Root directory of the unpacked wheel') - repack_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store the wheel (default %(default)s)") - repack_parser.add_argument('--build-number', help="Build tag to use in the wheel name") - repack_parser.set_defaults(func=pack_f) - - convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel') - convert_parser.add_argument('files', nargs='*', help='Files to convert') - convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store wheels (default %(default)s)") - convert_parser.add_argument('--verbose', '-v', action='store_true') - convert_parser.set_defaults(func=convert_f) - - version_parser = s.add_parser('version', help='Print version and exit') - version_parser.set_defaults(func=version_f) - - help_parser = s.add_parser('help', help='Show this help') - help_parser.set_defaults(func=lambda args: p.print_help()) - - return p - - -def main(): - p = parser() - args = p.parse_args() - if not hasattr(args, 'func'): - p.print_help() - else: - try: - args.func(args) - return 0 - except WheelError as e: - print(e, file=sys.stderr) - - return 1 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/__init__.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 5d1487696f571611e5aef8ec68889ed9a505d647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3000 zcmb_e%X1qw7?-qbd+n^9v`y1D-G;tg#z|pdIM6Aj4?4^+nNB-Q!3UO&B`2G%cU?)_ zHjBf7bcS-sAHXd+@-OMisb_AS_&)7ANkfm=vwD7#e)=B2Pj}nx7J*+v|M<~|)?e6} z{#flp~DIO!8kIZNn>^%=#slQ@0H)^6Xmb**3HF0Z{N{rW?~>%8%r@P=q?JAIFP zyb0q?-r_S*x46&SP|xrVpM~1zbNm?8ZGN1efV#t-C!{-HTxdOA7a|D;*=Q7{yqCnO z2yz`KvEE#2y#-*TOHF4i<5Y*kJRRsbOIHRIC*a56^WeJ&pZXMvO&@@ggly5LBwcig zrq5b(i4y#4#@VhjA$xS2{z`u!Df=F-4KSP)i5nKn*M7dabuCDR;3^nDTMMO7SuO`c z1=q)s)Il~3l+gKDXIY}UOI_Er-w`u2-;BnY)DNW0r12l;sg6gY?A3>v97VdzjGIOy zAssmJPa+ZhKc6k@(Rg_rk9%>dbd)5$7n#~9L_A)8iR!7!K@u;AVVuS~441~6W?qWt zc`QW;Aoij9u%W_T31!r$9V*cS1~@SN;brf@r%+aqK4`4ZI0a2GQ`*BqUg&Q76FioqSVVnr#a-pnpBe|yR>=8)DE7yj@Q?OK_ z^ApgIoQL`yWH@7yEkfh{$N-(Q?d+qIvmgoRT#L<>C!uSa94s@?ncOrUVhf>f{M9^8 zc$ns+RUx}fqKd5eQLuH~Djc4N`2(nDp!YvPZ49#Xg^;@I%Cm^JhDuZtRbv`3v6?9{ z#fJh%@inXU;qVg79zeVRy>}q)+ZnG?X_KOzAsU?tT_D@gwpMmm-lDUB9%sT3ASj6R zFf2T4}NSK@h%PUr^kA2J{E-Hway3M0UIIB$D3UFZG|Ix?&Aw+(L_$Pd*SFjKe;bc)4-$qdoA!&b}wh*fZS<*hM(o6t_OUE+&&KX>A8)UI(lm8=`?VTT$=z(D@72ii`Kk$P2{UT9C=$CGa_rKCZH7%X1)Q=#66TYYa&opT;UPwbarZYO7d&&kgJj zkgeVazi9S)Rb+!XUYM4>bf{&H`mIMcwc6mv$SW2eVa^SzKnfr^2jW$%tJ^H+v4FZ~e=sGCp_>QSF{Xbb9&ZFQiYw&!en&W@wh zJdrUt%(ldKP z;3-vur_@iBYyr;|$8~+ekiEEry!R9+oWsm7@T969RxTL5wj!^=Y4&wxV;DTTOqNXx z5F7%piMCLtu^y>NYbkrU#ID0vgv1169JQ%TU1=_)gzRq>g-&LuILiI*D2mf>VNPLc zC$tV~YS9*BP`Y%E229?C@$Rf?gdxuc<=bYM>l|KEp+xtUA7k-37GGk4x--oOuLfd_ xDr7g}s#B{SYV&gVLzpt?~tR+h&~8Fzzy+d4SJzyvCgC)vEuce*w?2&JO?p diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/convert.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/convert.cpython-37.pyc deleted file mode 100644 index b6c8d4c76d2d883fca47a7c084f6d124038f7d08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6170 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 EzYm~|!~g&Q diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/install.cpython-37.pyc b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/__pycache__/install.cpython-37.pyc deleted file mode 100644 index 8aaffae88a0b90bd887c745bbaae963332fb7014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmZ?b<>g`kf*i(~aUl9Jh=2h`Aj1KOi&=m~3PUi1CZpdU7OSkab`Fn$qzmNfClo>BwMN0aLOy~|dqlKxA z+&rVqJh8-w%4Ak);ocejh9>RYl=pyUU(#}uIcub_lwCTxHKApV)h4vCnOiuD9J^)x z70E4DpO{5Wd3o)Oes^5Bhoq=~{UCRD$d@~XmwRP{c@rxBmDkHAtmar_0v4>1vNZwS zlsx^m;%Nd8&aUhi&eLz7ki0Jc4VKN77FvPUJ|WEgoIE6dCb_}fle+kCZX`zT6vlM@ zJr&>N2K39h&04v!LViaII|q&v^UdCeY(6)ZNjc9JCNweFV$r};u=bhp-DctDZn-ca zMN=)7?YxmUCk9&mJ(YvJnKwXQ6F9C-2qiEs!9JYj(k^wKU1Lix!FKdK_R68-mvq9i7_#XMYWtSvNf>#*F{^c zup6+q2w%R#-uQuzeN@-dCx3?gR2uU`_bxY-<28?|PmO&*LNRUxIk!$sc!jANaWM z4@Xk@{WMWwl=x}F{Z#nFRB&H~htij+uZ}_m9TLPLSCzP_>gsz;Aip0b{sH$HS6mFE zgtM92%`6n*@Y2T3%8>tef=cwoCtRu?oNd$JfmxJ!S*7OEp{M-t4_)^Qpoy18@z(c|9zy?dYb9`0&;7^?nJ$IwRi18ocvtUGVQ zBy7-q{+kUo%r>$pgQ6l;7{}|+Qh7Y)QMOU}cGmafXal3&&7PloTQL-&emcyySMdxM zbPh4-c(vl#iqn1=%kAzZ+iN`g`1U8@rYM6@UjpEbmm)6xK{`qppvQkvjNji&e*&98 z!9i_SJNL9*;c09?4i7i|bLx+4vjRE(801wz0su=4Po-vxzmE_$NeUsmfXxhIZ^0K; zoYVDjVI3B57FoTeRC{PX&jb{a>#h)N4~${`8g&ng6Iwv zD>zII5*Y9w86?(#wgYWu%FodF8V~amHSS(&)U-RUzbMvU6y4LKSku$->a<=($>A)7 zp#)HMyIqYxXOkyP8=wBE^R93}imoA^F^9~UCjx(&+8Lw*l1JdBLNt(KABuF8i5e2{ z&#J97cidp7c}3wIz7Sbo1^P_aE%^_P+Q8^V5=} zgG9SZz%?OMT-&E2g29ogP@D-&ENxde32n;f5;hb|M@rj+cqEU4M#bL4>L)wbL<`wn zHmg^K0t*U&AhVuXjbpd{q%D zeZ8vm(1Ervsk9YCt|vpDSYA>>!kev28aI@0WDn8h-vg$EI;(sf{0=xLyVoJxo{ z{SM^^#_6B}8$bdNClLQw_4+5clnFv`t;ZrAuZTW^MW_a~Y^@;8`-nMp>yHFu3=mb+Q0TSV-h@qK=v4-^$R~4de!H1Qew{i*V#q@;k)-YwGm~Ufs RlMB!_!B%+Tq<8|){2$OC@1pgyCDI}>Guz7M#xWm{3Qo2Pk{A95P}GrlY+*S z;+^FzcDmDzUEv5f_XlkP5uDm5(I&0Rt#useW zTe@qCfW9(HOfc`S!Zo2}$yPh~L&*^l-YfE&yeDAqUt&2P0PS7;epl8>dcqTahLEB# zrxirQv5;p7T$VH=U^z+*Euaq&DqnQ6`0K_ZO#9wf8ZEl6<4<;$)hendF!u zIhGuac~T1A+4Ib34vrc+v&}oM6O|NTZ)Riuw(~SIOovgn01@BT4l#`RbC6k?V1v2H zluS*f&iOqdr%96=^iCV4u#kVh!>EI2dx!`iT-@BWAuEr;e#{qb6h#&%<;YSTTK4kA zaG+cmNqh|;YAGgD7#@0C?^sn$ZCRzQi@>crud>p5-RP}9tyGa1>*#ZBeQiY580$^* zM$c?0KO2>#Cdu=mrv?z+x>!=o&Zf%8WIOoW*7k#_+o1dPU}TDVRA=>mR%-O!Kdtoq zLT2@->(ExFc{bV%EUM3~zq#Ue={*pnAJPHcqc>.+?)-(?P.+?) - (-(?Ppy\d\.\d+) - (-(?P.+?))? - )?.egg$''', re.VERBOSE) - - -class _bdist_wheel_tag(bdist_wheel): - # allow the client to override the default generated wheel tag - # The default bdist_wheel implementation uses python and abi tags - # of the running python process. This is not suitable for - # generating/repackaging prebuild binaries. - - full_tag_supplied = False - full_tag = None # None or a (pytag, soabitag, plattag) triple - - def get_tag(self): - if self.full_tag_supplied and self.full_tag is not None: - return self.full_tag - else: - return bdist_wheel.get_tag(self) - - -def egg2wheel(egg_path, dest_dir): - filename = os.path.basename(egg_path) - match = egg_info_re.match(filename) - if not match: - raise WheelError('Invalid egg file name: {}'.format(filename)) - - egg_info = match.groupdict() - dir = tempfile.mkdtemp(suffix="_e2w") - if os.path.isfile(egg_path): - # assume we have a bdist_egg otherwise - with zipfile.ZipFile(egg_path) as egg: - egg.extractall(dir) - else: - # support buildout-style installed eggs directories - for pth in os.listdir(egg_path): - src = os.path.join(egg_path, pth) - if os.path.isfile(src): - shutil.copy2(src, dir) - else: - shutil.copytree(src, os.path.join(dir, pth)) - - pyver = egg_info['pyver'] - if pyver: - pyver = egg_info['pyver'] = pyver.replace('.', '') - - arch = (egg_info['arch'] or 'any').replace('.', '_').replace('-', '_') - - # assume all binary eggs are for CPython - abi = 'cp' + pyver[2:] if arch != 'any' else 'none' - - root_is_purelib = egg_info['arch'] is None - if root_is_purelib: - bw = bdist_wheel(dist.Distribution()) - else: - bw = _bdist_wheel_tag(dist.Distribution()) - - bw.root_is_pure = root_is_purelib - bw.python_tag = pyver - bw.plat_name_supplied = True - bw.plat_name = egg_info['arch'] or 'any' - if not root_is_purelib: - bw.full_tag_supplied = True - bw.full_tag = (pyver, abi, arch) - - dist_info_dir = os.path.join(dir, '{name}-{ver}.dist-info'.format(**egg_info)) - bw.egg2dist(os.path.join(dir, 'EGG-INFO'), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='egg2wheel') - wheel_name = '{name}-{ver}-{pyver}-{}-{}.whl'.format(abi, arch, **egg_info) - with WheelFile(os.path.join(dest_dir, wheel_name), 'w') as wf: - wf.write_files(dir) - - shutil.rmtree(dir) - - -def parse_wininst_info(wininfo_name, egginfo_name): - """Extract metadata from filenames. - - Extracts the 4 metadataitems needed (name, version, pyversion, arch) from - the installer filename and the name of the egg-info directory embedded in - the zipfile (if any). - - The egginfo filename has the format:: - - name-ver(-pyver)(-arch).egg-info - - The installer filename has the format:: - - name-ver.arch(-pyver).exe - - Some things to note: - - 1. The installer filename is not definitive. An installer can be renamed - and work perfectly well as an installer. So more reliable data should - be used whenever possible. - 2. The egg-info data should be preferred for the name and version, because - these come straight from the distutils metadata, and are mandatory. - 3. The pyver from the egg-info data should be ignored, as it is - constructed from the version of Python used to build the installer, - which is irrelevant - the installer filename is correct here (even to - the point that when it's not there, any version is implied). - 4. The architecture must be taken from the installer filename, as it is - not included in the egg-info data. - 5. Architecture-neutral installers still have an architecture because the - installer format itself (being executable) is architecture-specific. We - should therefore ignore the architecture if the content is pure-python. - """ - - egginfo = None - if egginfo_name: - egginfo = egg_info_re.search(egginfo_name) - if not egginfo: - raise ValueError("Egg info filename %s is not valid" % (egginfo_name,)) - - # Parse the wininst filename - # 1. Distribution name (up to the first '-') - w_name, sep, rest = wininfo_name.partition('-') - if not sep: - raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) - - # Strip '.exe' - rest = rest[:-4] - # 2. Python version (from the last '-', must start with 'py') - rest2, sep, w_pyver = rest.rpartition('-') - if sep and w_pyver.startswith('py'): - rest = rest2 - w_pyver = w_pyver.replace('.', '') - else: - # Not version specific - use py2.py3. While it is possible that - # pure-Python code is not compatible with both Python 2 and 3, there - # is no way of knowing from the wininst format, so we assume the best - # here (the user can always manually rename the wheel to be more - # restrictive if needed). - w_pyver = 'py2.py3' - # 3. Version and architecture - w_ver, sep, w_arch = rest.rpartition('.') - if not sep: - raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) - - if egginfo: - w_name = egginfo.group('name') - w_ver = egginfo.group('ver') - - return {'name': w_name, 'ver': w_ver, 'arch': w_arch, 'pyver': w_pyver} - - -def wininst2wheel(path, dest_dir): - with zipfile.ZipFile(path) as bdw: - # Search for egg-info in the archive - egginfo_name = None - for filename in bdw.namelist(): - if '.egg-info' in filename: - egginfo_name = filename - break - - info = parse_wininst_info(os.path.basename(path), egginfo_name) - - root_is_purelib = True - for zipinfo in bdw.infolist(): - if zipinfo.filename.startswith('PLATLIB'): - root_is_purelib = False - break - if root_is_purelib: - paths = {'purelib': ''} - else: - paths = {'platlib': ''} - - dist_info = "%(name)s-%(ver)s" % info - datadir = "%s.data/" % dist_info - - # rewrite paths to trick ZipFile into extracting an egg - # XXX grab wininst .ini - between .exe, padding, and first zip file. - members = [] - egginfo_name = '' - for zipinfo in bdw.infolist(): - key, basename = zipinfo.filename.split('/', 1) - key = key.lower() - basepath = paths.get(key, None) - if basepath is None: - basepath = datadir + key.lower() + '/' - oldname = zipinfo.filename - newname = basepath + basename - zipinfo.filename = newname - del bdw.NameToInfo[oldname] - bdw.NameToInfo[newname] = zipinfo - # Collect member names, but omit '' (from an entry like "PLATLIB/" - if newname: - members.append(newname) - # Remember egg-info name for the egg2dist call below - if not egginfo_name: - if newname.endswith('.egg-info'): - egginfo_name = newname - elif '.egg-info/' in newname: - egginfo_name, sep, _ = newname.rpartition('/') - dir = tempfile.mkdtemp(suffix="_b2w") - bdw.extractall(dir, members) - - # egg2wheel - abi = 'none' - pyver = info['pyver'] - arch = (info['arch'] or 'any').replace('.', '_').replace('-', '_') - # Wininst installers always have arch even if they are not - # architecture-specific (because the format itself is). - # So, assume the content is architecture-neutral if root is purelib. - if root_is_purelib: - arch = 'any' - # If the installer is architecture-specific, it's almost certainly also - # CPython-specific. - if arch != 'any': - pyver = pyver.replace('py', 'cp') - wheel_name = '-'.join((dist_info, pyver, abi, arch)) - if root_is_purelib: - bw = bdist_wheel(dist.Distribution()) - else: - bw = _bdist_wheel_tag(dist.Distribution()) - - bw.root_is_pure = root_is_purelib - bw.python_tag = pyver - bw.plat_name_supplied = True - bw.plat_name = info['arch'] or 'any' - - if not root_is_purelib: - bw.full_tag_supplied = True - bw.full_tag = (pyver, abi, arch) - - dist_info_dir = os.path.join(dir, '%s.dist-info' % dist_info) - bw.egg2dist(os.path.join(dir, egginfo_name), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='wininst2wheel') - - wheel_path = os.path.join(dest_dir, wheel_name) - with WheelFile(wheel_path, 'w') as wf: - wf.write_files(dir) - - shutil.rmtree(dir) - - -def convert(files, dest_dir, verbose): - # Only support wheel convert if pkg_resources is present - require_pkgresources('wheel convert') - - for pat in files: - for installer in iglob(pat): - if os.path.splitext(installer)[1] == '.egg': - conv = egg2wheel - else: - conv = wininst2wheel - - if verbose: - print("{}... ".format(installer)) - sys.stdout.flush() - - conv(installer, dest_dir) - if verbose: - print("OK") diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/install.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/install.py deleted file mode 100644 index e69de29..0000000 diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/pack.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/pack.py deleted file mode 100644 index 1e77fdb..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/pack.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import print_function - -import os.path -import re -import sys - -from wheel.cli import WheelError -from wheel.wheelfile import WheelFile - -DIST_INFO_RE = re.compile(r"^(?P(?P.+?)-(?P\d.*?))\.dist-info$") -BUILD_NUM_RE = re.compile(br'Build: (\d\w*)$') - - -def pack(directory, dest_dir, build_number): - """Repack a previously unpacked wheel directory into a new wheel file. - - The .dist-info/WHEEL file must contain one or more tags so that the target - wheel file name can be determined. - - :param directory: The unpacked wheel directory - :param dest_dir: Destination directory (defaults to the current directory) - """ - # Find the .dist-info directory - dist_info_dirs = [fn for fn in os.listdir(directory) - if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn)] - if len(dist_info_dirs) > 1: - raise WheelError('Multiple .dist-info directories found in {}'.format(directory)) - elif not dist_info_dirs: - raise WheelError('No .dist-info directories found in {}'.format(directory)) - - # Determine the target wheel filename - dist_info_dir = dist_info_dirs[0] - name_version = DIST_INFO_RE.match(dist_info_dir).group('namever') - - # Read the tags and the existing build number from .dist-info/WHEEL - existing_build_number = None - wheel_file_path = os.path.join(directory, dist_info_dir, 'WHEEL') - with open(wheel_file_path) as f: - tags = [] - for line in f: - if line.startswith('Tag: '): - tags.append(line.split(' ')[1].rstrip()) - elif line.startswith('Build: '): - existing_build_number = line.split(' ')[1].rstrip() - - if not tags: - raise WheelError('No tags present in {}/WHEEL; cannot determine target wheel filename' - .format(dist_info_dir)) - - # Set the wheel file name and add/replace/remove the Build tag in .dist-info/WHEEL - build_number = build_number if build_number is not None else existing_build_number - if build_number is not None: - if build_number: - name_version += '-' + build_number - - if build_number != existing_build_number: - replacement = ('Build: %s\r\n' % build_number).encode('ascii') if build_number else b'' - with open(wheel_file_path, 'rb+') as f: - wheel_file_content = f.read() - if not BUILD_NUM_RE.subn(replacement, wheel_file_content)[1]: - wheel_file_content += replacement - - f.truncate() - f.write(wheel_file_content) - - # Reassemble the tags for the wheel file - impls = sorted({tag.split('-')[0] for tag in tags}) - abivers = sorted({tag.split('-')[1] for tag in tags}) - platforms = sorted({tag.split('-')[2] for tag in tags}) - tagline = '-'.join(['.'.join(impls), '.'.join(abivers), '.'.join(platforms)]) - - # Repack the wheel - wheel_path = os.path.join(dest_dir, '{}-{}.whl'.format(name_version, tagline)) - with WheelFile(wheel_path, 'w') as wf: - print("Repacking wheel as {}...".format(wheel_path), end='') - sys.stdout.flush() - wf.write_files(directory) - - print('OK') diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/unpack.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/unpack.py deleted file mode 100644 index 2e9857a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/cli/unpack.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import print_function - -import os.path -import sys - -from ..wheelfile import WheelFile - - -def unpack(path, dest='.'): - """Unpack a wheel. - - Wheel content will be unpacked to {dest}/{name}-{ver}, where {name} - is the package name and {ver} its version. - - :param path: The path to the wheel. - :param dest: Destination directory (default to current directory). - """ - with WheelFile(path) as wf: - namever = wf.parsed_filename.group('namever') - destination = os.path.join(dest, namever) - print("Unpacking to: {}...".format(destination), end='') - sys.stdout.flush() - wf.extractall(destination) - - print('OK') diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/macosx_libfile.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/macosx_libfile.py deleted file mode 100644 index a903688..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/macosx_libfile.py +++ /dev/null @@ -1,341 +0,0 @@ -""" -This module contains function to analyse dynamic library -headers to extract system information - -Currently only for MacOSX - -Library file on macosx system starts with Mach-O or Fat field. -This can be distinguish by first 32 bites and it is called magic number. -Proper value of magic number is with suffix _MAGIC. Suffix _CIGAM means -reversed bytes order. -Both fields can occur in two types: 32 and 64 bytes. - -FAT field inform that this library contains few version of library -(typically for different types version). It contains -information where Mach-O headers starts. - -Each section started with Mach-O header contains one library -(So if file starts with this field it contains only one version). - -After filed Mach-O there are section fields. -Each of them starts with two fields: -cmd - magic number for this command -cmdsize - total size occupied by this section information. - -In this case only sections LC_VERSION_MIN_MACOSX (for macosx 10.13 and earlier) -and LC_BUILD_VERSION (for macosx 10.14 and newer) are interesting, -because them contains information about minimal system version. - -Important remarks: -- For fat files this implementation looks for maximum number version. - It not check if it is 32 or 64 and do not compare it with currently builded package. - So it is possible to false report higher version that needed. -- All structures signatures are taken form macosx header files. -- I think that binary format will be more stable than `otool` output. - and if apple introduce some changes both implementation will need to be updated. -""" - -import ctypes -import sys - -"""here the needed const and struct from mach-o header files""" - -FAT_MAGIC = 0xcafebabe -FAT_CIGAM = 0xbebafeca -FAT_MAGIC_64 = 0xcafebabf -FAT_CIGAM_64 = 0xbfbafeca -MH_MAGIC = 0xfeedface -MH_CIGAM = 0xcefaedfe -MH_MAGIC_64 = 0xfeedfacf -MH_CIGAM_64 = 0xcffaedfe - -LC_VERSION_MIN_MACOSX = 0x24 -LC_BUILD_VERSION = 0x32 - - -mach_header_fields = [ - ("magic", ctypes.c_uint32), ("cputype", ctypes.c_int), - ("cpusubtype", ctypes.c_int), ("filetype", ctypes.c_uint32), - ("ncmds", ctypes.c_uint32), ("sizeofcmds", ctypes.c_uint32), - ("flags", ctypes.c_uint32) - ] -""" -struct mach_header { - uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ - uint32_t filetype; /* type of file */ - uint32_t ncmds; /* number of load commands */ - uint32_t sizeofcmds; /* the size of all the load commands */ - uint32_t flags; /* flags */ -}; -typedef integer_t cpu_type_t; -typedef integer_t cpu_subtype_t; -""" - -mach_header_fields_64 = mach_header_fields + [("reserved", ctypes.c_uint32)] -""" -struct mach_header_64 { - uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ - uint32_t filetype; /* type of file */ - uint32_t ncmds; /* number of load commands */ - uint32_t sizeofcmds; /* the size of all the load commands */ - uint32_t flags; /* flags */ - uint32_t reserved; /* reserved */ -}; -""" - -fat_header_fields = [("magic", ctypes.c_uint32), ("nfat_arch", ctypes.c_uint32)] -""" -struct fat_header { - uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ - uint32_t nfat_arch; /* number of structs that follow */ -}; -""" - -fat_arch_fields = [ - ("cputype", ctypes.c_int), ("cpusubtype", ctypes.c_int), - ("offset", ctypes.c_uint32), ("size", ctypes.c_uint32), - ("align", ctypes.c_uint32) -] -""" -struct fat_arch { - cpu_type_t cputype; /* cpu specifier (int) */ - cpu_subtype_t cpusubtype; /* machine specifier (int) */ - uint32_t offset; /* file offset to this object file */ - uint32_t size; /* size of this object file */ - uint32_t align; /* alignment as a power of 2 */ -}; -""" - -fat_arch_64_fields = [ - ("cputype", ctypes.c_int), ("cpusubtype", ctypes.c_int), - ("offset", ctypes.c_uint64), ("size", ctypes.c_uint64), - ("align", ctypes.c_uint32), ("reserved", ctypes.c_uint32) -] -""" -struct fat_arch_64 { - cpu_type_t cputype; /* cpu specifier (int) */ - cpu_subtype_t cpusubtype; /* machine specifier (int) */ - uint64_t offset; /* file offset to this object file */ - uint64_t size; /* size of this object file */ - uint32_t align; /* alignment as a power of 2 */ - uint32_t reserved; /* reserved */ -}; -""" - -segment_base_fields = [("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32)] -"""base for reading segment info""" - -segment_command_fields = [ - ("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32), - ("segname", ctypes.c_char * 16), ("vmaddr", ctypes.c_uint32), - ("vmsize", ctypes.c_uint32), ("fileoff", ctypes.c_uint32), - ("filesize", ctypes.c_uint32), ("maxprot", ctypes.c_int), - ("initprot", ctypes.c_int), ("nsects", ctypes.c_uint32), - ("flags", ctypes.c_uint32), - ] -""" -struct segment_command { /* for 32-bit architectures */ - uint32_t cmd; /* LC_SEGMENT */ - uint32_t cmdsize; /* includes sizeof section structs */ - char segname[16]; /* segment name */ - uint32_t vmaddr; /* memory address of this segment */ - uint32_t vmsize; /* memory size of this segment */ - uint32_t fileoff; /* file offset of this segment */ - uint32_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ - uint32_t nsects; /* number of sections in segment */ - uint32_t flags; /* flags */ -}; -typedef int vm_prot_t; -""" - -segment_command_fields_64 = [ - ("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32), - ("segname", ctypes.c_char * 16), ("vmaddr", ctypes.c_uint64), - ("vmsize", ctypes.c_uint64), ("fileoff", ctypes.c_uint64), - ("filesize", ctypes.c_uint64), ("maxprot", ctypes.c_int), - ("initprot", ctypes.c_int), ("nsects", ctypes.c_uint32), - ("flags", ctypes.c_uint32), - ] -""" -struct segment_command_64 { /* for 64-bit architectures */ - uint32_t cmd; /* LC_SEGMENT_64 */ - uint32_t cmdsize; /* includes sizeof section_64 structs */ - char segname[16]; /* segment name */ - uint64_t vmaddr; /* memory address of this segment */ - uint64_t vmsize; /* memory size of this segment */ - uint64_t fileoff; /* file offset of this segment */ - uint64_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ - uint32_t nsects; /* number of sections in segment */ - uint32_t flags; /* flags */ -}; -""" - -version_min_command_fields = segment_base_fields + \ - [("version", ctypes.c_uint32), ("sdk", ctypes.c_uint32)] -""" -struct version_min_command { - uint32_t cmd; /* LC_VERSION_MIN_MACOSX or - LC_VERSION_MIN_IPHONEOS or - LC_VERSION_MIN_WATCHOS or - LC_VERSION_MIN_TVOS */ - uint32_t cmdsize; /* sizeof(struct min_version_command) */ - uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ -}; -""" - -build_version_command_fields = segment_base_fields + \ - [("platform", ctypes.c_uint32), ("minos", ctypes.c_uint32), - ("sdk", ctypes.c_uint32), ("ntools", ctypes.c_uint32)] -""" -struct build_version_command { - uint32_t cmd; /* LC_BUILD_VERSION */ - uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ - /* ntools * sizeof(struct build_tool_version) */ - uint32_t platform; /* platform */ - uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t ntools; /* number of tool entries following this */ -}; -""" - - -def swap32(x): - return (((x << 24) & 0xFF000000) | - ((x << 8) & 0x00FF0000) | - ((x >> 8) & 0x0000FF00) | - ((x >> 24) & 0x000000FF)) - - -def get_base_class_and_magic_number(lib_file, seek=None): - if seek is None: - seek = lib_file.tell() - else: - lib_file.seek(seek) - magic_number = ctypes.c_uint32.from_buffer_copy( - lib_file.read(ctypes.sizeof(ctypes.c_uint32))).value - - # Handle wrong byte order - if magic_number in [FAT_CIGAM, FAT_CIGAM_64, MH_CIGAM, MH_CIGAM_64]: - if sys.byteorder == "little": - BaseClass = ctypes.BigEndianStructure - else: - BaseClass = ctypes.LittleEndianStructure - - magic_number = swap32(magic_number) - else: - BaseClass = ctypes.Structure - - lib_file.seek(seek) - return BaseClass, magic_number - - -def read_data(struct_class, lib_file): - return struct_class.from_buffer_copy(lib_file.read( - ctypes.sizeof(struct_class))) - - -def extract_macosx_min_system_version(path_to_lib): - with open(path_to_lib, "rb") as lib_file: - BaseClass, magic_number = get_base_class_and_magic_number(lib_file, 0) - if magic_number not in [FAT_MAGIC, FAT_MAGIC_64, MH_MAGIC, MH_MAGIC_64]: - return - - if magic_number in [FAT_MAGIC, FAT_CIGAM_64]: - class FatHeader(BaseClass): - _fields_ = fat_header_fields - - fat_header = read_data(FatHeader, lib_file) - if magic_number == FAT_MAGIC: - - class FatArch(BaseClass): - _fields_ = fat_arch_fields - else: - - class FatArch(BaseClass): - _fields_ = fat_arch_64_fields - - fat_arch_list = [read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch)] - - versions_list = [] - for el in fat_arch_list: - try: - version = read_mach_header(lib_file, el.offset) - if version is not None: - versions_list.append(version) - except ValueError: - pass - - if len(versions_list) > 0: - return max(versions_list) - else: - return None - - else: - try: - return read_mach_header(lib_file, 0) - except ValueError: - """when some error during read library files""" - return None - - -def read_mach_header(lib_file, seek=None): - """ - This funcition parse mach-O header and extract - information about minimal system version - - :param lib_file: reference to opened library file with pointer - """ - if seek is not None: - lib_file.seek(seek) - base_class, magic_number = get_base_class_and_magic_number(lib_file) - arch = "32" if magic_number == MH_MAGIC else "64" - - class SegmentBase(base_class): - _fields_ = segment_base_fields - - if arch == "32": - - class MachHeader(base_class): - _fields_ = mach_header_fields - - else: - - class MachHeader(base_class): - _fields_ = mach_header_fields_64 - - mach_header = read_data(MachHeader, lib_file) - for _i in range(mach_header.ncmds): - pos = lib_file.tell() - segment_base = read_data(SegmentBase, lib_file) - lib_file.seek(pos) - if segment_base.cmd == LC_VERSION_MIN_MACOSX: - class VersionMinCommand(base_class): - _fields_ = version_min_command_fields - - version_info = read_data(VersionMinCommand, lib_file) - return parse_version(version_info.version) - elif segment_base.cmd == LC_BUILD_VERSION: - class VersionBuild(base_class): - _fields_ = build_version_command_fields - - version_info = read_data(VersionBuild, lib_file) - return parse_version(version_info.minos) - else: - lib_file.seek(pos + segment_base.cmdsize) - continue - - -def parse_version(version): - x = (version & 0xffff0000) >> 16 - y = (version & 0x0000ff00) >> 8 - z = (version & 0x000000ff) - return x, y, z diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/metadata.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/metadata.py deleted file mode 100644 index bbf57a7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/metadata.py +++ /dev/null @@ -1,138 +0,0 @@ -""" -Tools for converting old- to new-style metadata. -""" - -import os.path -import re -import textwrap - -import pkg_resources - -from .pkginfo import read_pkg_info - -# Support markers syntax with the extra at the end only -EXTRA_RE = re.compile( - r"""^(?P.*?)(;\s*(?P.*?)(extra == '(?P.*?)')?)$""") - - -def requires_to_requires_dist(requirement): - """Return the version specifier for a requirement in PEP 345/566 fashion.""" - if getattr(requirement, 'url', None): - return " @ " + requirement.url - - requires_dist = [] - for op, ver in requirement.specs: - requires_dist.append(op + ver) - if not requires_dist: - return '' - return " (%s)" % ','.join(sorted(requires_dist)) - - -def convert_requirements(requirements): - """Yield Requires-Dist: strings for parsed requirements strings.""" - for req in requirements: - parsed_requirement = pkg_resources.Requirement.parse(req) - spec = requires_to_requires_dist(parsed_requirement) - extras = ",".join(sorted(parsed_requirement.extras)) - if extras: - extras = "[%s]" % extras - yield (parsed_requirement.project_name + extras + spec) - - -def generate_requirements(extras_require): - """ - Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') - and ('Provides-Extra', 'extra') tuples. - - extras_require is a dictionary of {extra: [requirements]} as passed to setup(), - using the empty extra {'': [requirements]} to hold install_requires. - """ - for extra, depends in extras_require.items(): - condition = '' - extra = extra or '' - if ':' in extra: # setuptools extra:condition syntax - extra, condition = extra.split(':', 1) - - extra = pkg_resources.safe_extra(extra) - if extra: - yield 'Provides-Extra', extra - if condition: - condition = "(" + condition + ") and " - condition += "extra == '%s'" % extra - - if condition: - condition = ' ; ' + condition - - for new_req in convert_requirements(depends): - yield 'Requires-Dist', new_req + condition - - -def pkginfo_to_metadata(egg_info_path, pkginfo_path): - """ - Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format - """ - pkg_info = read_pkg_info(pkginfo_path) - pkg_info.replace_header('Metadata-Version', '2.1') - # Those will be regenerated from `requires.txt`. - del pkg_info['Provides-Extra'] - del pkg_info['Requires-Dist'] - requires_path = os.path.join(egg_info_path, 'requires.txt') - if os.path.exists(requires_path): - with open(requires_path) as requires_file: - requires = requires_file.read() - - parsed_requirements = sorted(pkg_resources.split_sections(requires), - key=lambda x: x[0] or '') - for extra, reqs in parsed_requirements: - for key, value in generate_requirements({extra: reqs}): - if (key, value) not in pkg_info.items(): - pkg_info[key] = value - - description = pkg_info['Description'] - if description: - pkg_info.set_payload(dedent_description(pkg_info)) - del pkg_info['Description'] - - return pkg_info - - -def pkginfo_unicode(pkg_info, field): - """Hack to coax Unicode out of an email Message() - Python 3.3+""" - text = pkg_info[field] - field = field.lower() - if not isinstance(text, str): - for item in pkg_info.raw_items(): - if item[0].lower() == field: - text = item[1].encode('ascii', 'surrogateescape') \ - .decode('utf-8') - break - - return text - - -def dedent_description(pkg_info): - """ - Dedent and convert pkg_info['Description'] to Unicode. - """ - description = pkg_info['Description'] - - # Python 3 Unicode handling, sorta. - surrogates = False - if not isinstance(description, str): - surrogates = True - description = pkginfo_unicode(pkg_info, 'Description') - - description_lines = description.splitlines() - description_dedent = '\n'.join( - # if the first line of long_description is blank, - # the first line here will be indented. - (description_lines[0].lstrip(), - textwrap.dedent('\n'.join(description_lines[1:])), - '\n')) - - if surrogates: - description_dedent = description_dedent \ - .encode("utf8") \ - .decode("ascii", "surrogateescape") - - return description_dedent diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pep425tags.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pep425tags.py deleted file mode 100644 index 0c25763..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pep425tags.py +++ /dev/null @@ -1,261 +0,0 @@ -"""Generate and work with PEP 425 Compatibility Tags.""" - -import distutils.util -import platform -import sys -import os -import sysconfig -import warnings - -from .macosx_libfile import extract_macosx_min_system_version - - -try: - from importlib.machinery import all_suffixes as get_all_suffixes -except ImportError: - from imp import get_suffixes - - def get_all_suffixes(): - return [suffix[0] for suffix in get_suffixes()] - - -def get_config_var(var): - try: - return sysconfig.get_config_var(var) - except IOError as e: # pip Issue #1074 - warnings.warn("{0}".format(e), RuntimeWarning) - return None - - -def get_abbr_impl(): - """Return abbreviated implementation name.""" - impl = platform.python_implementation() - if impl == 'PyPy': - return 'pp' - elif impl == 'Jython': - return 'jy' - elif impl == 'IronPython': - return 'ip' - elif impl == 'CPython': - return 'cp' - - raise LookupError('Unknown Python implementation: ' + impl) - - -def get_impl_ver(): - """Return implementation version.""" - impl_ver = get_config_var("py_version_nodot") - if not impl_ver: - impl_ver = ''.join(map(str, get_impl_version_info())) - return impl_ver - - -def get_impl_version_info(): - """Return sys.version_info-like tuple for use in decrementing the minor - version.""" - return sys.version_info[0], sys.version_info[1] - - -def get_flag(var, fallback, expected=True, warn=True): - """Use a fallback method for determining SOABI flags if the needed config - var is unset or unavailable.""" - val = get_config_var(var) - if val is None: - if warn: - warnings.warn("Config variable '{0}' is unset, Python ABI tag may " - "be incorrect".format(var), RuntimeWarning, 2) - return fallback() - return val == expected - - -def get_abi_tag(): - """Return the ABI tag based on SOABI (if available) or emulate SOABI - (CPython 2, PyPy).""" - soabi = get_config_var('SOABI') - impl = get_abbr_impl() - if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): - d = '' - m = '' - u = '' - if get_flag('Py_DEBUG', - lambda: hasattr(sys, 'gettotalrefcount'), - warn=(impl == 'cp')): - d = 'd' - if get_flag('WITH_PYMALLOC', - lambda: impl == 'cp', - warn=(impl == 'cp' and - sys.version_info < (3, 8))) \ - and sys.version_info < (3, 8): - m = 'm' - if get_flag('Py_UNICODE_SIZE', - lambda: sys.maxunicode == 0x10ffff, - expected=4, - warn=(impl == 'cp' and - sys.version_info < (3, 3))) \ - and sys.version_info < (3, 3): - u = 'u' - abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) - elif soabi and soabi.startswith('cpython-'): - abi = 'cp' + soabi.split('-')[1] - elif soabi: - abi = soabi.replace('.', '_').replace('-', '_') - else: - abi = None - return abi - - -def calculate_macosx_platform_tag(archive_root, platform_tag): - """ - Calculate proper macosx platform tag basing on files which are included to wheel - - Example platform tag `macosx-10.14-x86_64` - """ - prefix, base_version, suffix = platform_tag.split('-') - base_version = tuple([int(x) for x in base_version.split(".")]) - if len(base_version) >= 2: - base_version = base_version[0:2] - - assert len(base_version) == 2 - if "MACOSX_DEPLOYMENT_TARGET" in os.environ: - deploy_target = tuple([int(x) for x in os.environ[ - "MACOSX_DEPLOYMENT_TARGET"].split(".")]) - if len(deploy_target) >= 2: - deploy_target = deploy_target[0:2] - if deploy_target < base_version: - sys.stderr.write( - "[WARNING] MACOSX_DEPLOYMENT_TARGET is set to a lower value ({}) than the " - "version on which the Python interpreter was compiled ({}), and will be " - "ignored.\n".format('.'.join(str(x) for x in deploy_target), - '.'.join(str(x) for x in base_version)) - ) - else: - base_version = deploy_target - - assert len(base_version) == 2 - start_version = base_version - versions_dict = {} - for (dirpath, dirnames, filenames) in os.walk(archive_root): - for filename in filenames: - if filename.endswith('.dylib') or filename.endswith('.so'): - lib_path = os.path.join(dirpath, filename) - min_ver = extract_macosx_min_system_version(lib_path) - if min_ver is not None: - versions_dict[lib_path] = min_ver[0:2] - - if len(versions_dict) > 0: - base_version = max(base_version, max(versions_dict.values())) - - # macosx platform tag do not support minor bugfix release - fin_base_version = "_".join([str(x) for x in base_version]) - if start_version < base_version: - problematic_files = [k for k, v in versions_dict.items() if v > start_version] - problematic_files = "\n".join(problematic_files) - if len(problematic_files) == 1: - files_form = "this file" - else: - files_form = "these files" - error_message = \ - "[WARNING] This wheel needs a higher macOS version than {} " \ - "To silence this warning, set MACOSX_DEPLOYMENT_TARGET to at least " +\ - fin_base_version + " or recreate " + files_form + " with lower " \ - "MACOSX_DEPLOYMENT_TARGET: \n" + problematic_files - - if "MACOSX_DEPLOYMENT_TARGET" in os.environ: - error_message = error_message.format("is set in MACOSX_DEPLOYMENT_TARGET variable.") - else: - error_message = error_message.format( - "the version your Python interpreter is compiled against.") - - sys.stderr.write(error_message) - - platform_tag = prefix + "_" + fin_base_version + "_" + suffix - return platform_tag - - -def get_platform(archive_root): - """Return our platform name 'win32', 'linux_x86_64'""" - # XXX remove distutils dependency - result = distutils.util.get_platform() - if result.startswith("macosx") and archive_root is not None: - result = calculate_macosx_platform_tag(archive_root, result) - result = result.replace('.', '_').replace('-', '_') - if result == "linux_x86_64" and sys.maxsize == 2147483647: - # pip pull request #3497 - result = "linux_i686" - - return result - - -def get_supported(archive_root, versions=None, supplied_platform=None): - """Return a list of supported tags for each version specified in - `versions`. - - :param versions: a list of string versions, of the form ["33", "32"], - or None. The first version will be assumed to support our ABI. - """ - supported = [] - - # Versions must be given with respect to the preference - if versions is None: - versions = [] - version_info = get_impl_version_info() - major = version_info[:-1] - # Support all previous minor Python versions. - for minor in range(version_info[-1], -1, -1): - versions.append(''.join(map(str, major + (minor,)))) - - impl = get_abbr_impl() - - abis = [] - - abi = get_abi_tag() - if abi: - abis[0:0] = [abi] - - abi3s = set() - for suffix in get_all_suffixes(): - if suffix.startswith('.abi'): - abi3s.add(suffix.split('.', 2)[1]) - - abis.extend(sorted(list(abi3s))) - - abis.append('none') - - platforms = [] - if supplied_platform: - platforms.append(supplied_platform) - platforms.append(get_platform(archive_root)) - - # Current version, current API (built specifically for our Python): - for abi in abis: - for arch in platforms: - supported.append(('%s%s' % (impl, versions[0]), abi, arch)) - - # abi3 modules compatible with older version of Python - for version in versions[1:]: - # abi3 was introduced in Python 3.2 - if version in ('31', '30'): - break - for abi in abi3s: # empty set if not Python 3 - for arch in platforms: - supported.append(("%s%s" % (impl, version), abi, arch)) - - # No abi / arch, but requires our implementation: - for i, version in enumerate(versions): - supported.append(('%s%s' % (impl, version), 'none', 'any')) - if i == 0: - # Tagged specifically as being cross-version compatible - # (with just the major version specified) - supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) - - # Major Python version + platform; e.g. binaries not using the Python API - for arch in platforms: - supported.append(('py%s' % (versions[0][0]), 'none', arch)) - - # No abi / arch, generic Python - for i, version in enumerate(versions): - supported.append(('py%s' % (version,), 'none', 'any')) - if i == 0: - supported.append(('py%s' % (version[0]), 'none', 'any')) - - return supported diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pkginfo.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pkginfo.py deleted file mode 100644 index 115be45..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/pkginfo.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Tools for reading and writing PKG-INFO / METADATA without caring -about the encoding.""" - -from email.parser import Parser - -try: - unicode - _PY3 = False -except NameError: - _PY3 = True - -if not _PY3: - from email.generator import Generator - - def read_pkg_info_bytes(bytestr): - return Parser().parsestr(bytestr) - - def read_pkg_info(path): - with open(path, "r") as headers: - message = Parser().parse(headers) - return message - - def write_pkg_info(path, message): - with open(path, 'w') as metadata: - Generator(metadata, mangle_from_=False, maxheaderlen=0).flatten(message) -else: - from email.generator import BytesGenerator - - def read_pkg_info_bytes(bytestr): - headers = bytestr.decode(encoding="ascii", errors="surrogateescape") - message = Parser().parsestr(headers) - return message - - def read_pkg_info(path): - with open(path, "r", - encoding="ascii", - errors="surrogateescape") as headers: - message = Parser().parse(headers) - return message - - def write_pkg_info(path, message): - with open(path, "wb") as out: - BytesGenerator(out, mangle_from_=False, maxheaderlen=0).flatten(message) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/util.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/util.py deleted file mode 100644 index 3ae2b44..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/util.py +++ /dev/null @@ -1,46 +0,0 @@ -import base64 -import io -import sys - - -if sys.version_info[0] < 3: - text_type = unicode # noqa: F821 - - StringIO = io.BytesIO - - def native(s, encoding='utf-8'): - if isinstance(s, unicode): # noqa: F821 - return s.encode(encoding) - return s -else: - text_type = str - - StringIO = io.StringIO - - def native(s, encoding='utf-8'): - if isinstance(s, bytes): - return s.decode(encoding) - return s - - -def urlsafe_b64encode(data): - """urlsafe_b64encode without padding""" - return base64.urlsafe_b64encode(data).rstrip(b'=') - - -def urlsafe_b64decode(data): - """urlsafe_b64decode without padding""" - pad = b'=' * (4 - (len(data) & 3)) - return base64.urlsafe_b64decode(data + pad) - - -def as_unicode(s): - if isinstance(s, bytes): - return s.decode('utf-8') - return s - - -def as_bytes(s): - if isinstance(s, text_type): - return s.encode('utf-8') - return s diff --git a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/wheelfile.py b/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/wheelfile.py deleted file mode 100644 index acc5dab..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site-packages/wheel/wheelfile.py +++ /dev/null @@ -1,169 +0,0 @@ -from __future__ import print_function - -import csv -import hashlib -import os.path -import re -import stat -import time -from collections import OrderedDict -from distutils import log as logger -from zipfile import ZIP_DEFLATED, ZipInfo, ZipFile - -from wheel.cli import WheelError -from wheel.util import urlsafe_b64decode, as_unicode, native, urlsafe_b64encode, as_bytes, StringIO - -# Non-greedy matching of an optional build number may be too clever (more -# invalid wheel filenames will match). Separate regex for .dist-info? -WHEEL_INFO_RE = re.compile( - r"""^(?P(?P.+?)-(?P.+?))(-(?P\d[^-]*))? - -(?P.+?)-(?P.+?)-(?P.+?)\.whl$""", - re.VERBOSE) - - -def get_zipinfo_datetime(timestamp=None): - # Some applications need reproducible .whl files, but they can't do this without forcing - # the timestamp of the individual ZipInfo objects. See issue #143. - timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timestamp or time.time())) - return time.gmtime(timestamp)[0:6] - - -class WheelFile(ZipFile): - """A ZipFile derivative class that also reads SHA-256 hashes from - .dist-info/RECORD and checks any read files against those. - """ - - _default_algorithm = hashlib.sha256 - - def __init__(self, file, mode='r', compression=ZIP_DEFLATED): - basename = os.path.basename(file) - self.parsed_filename = WHEEL_INFO_RE.match(basename) - if not basename.endswith('.whl') or self.parsed_filename is None: - raise WheelError("Bad wheel filename {!r}".format(basename)) - - ZipFile.__init__(self, file, mode, compression=compression, allowZip64=True) - - self.dist_info_path = '{}.dist-info'.format(self.parsed_filename.group('namever')) - self.record_path = self.dist_info_path + '/RECORD' - self._file_hashes = OrderedDict() - self._file_sizes = {} - if mode == 'r': - # Ignore RECORD and any embedded wheel signatures - self._file_hashes[self.record_path] = None, None - self._file_hashes[self.record_path + '.jws'] = None, None - self._file_hashes[self.record_path + '.p7s'] = None, None - - # Fill in the expected hashes by reading them from RECORD - try: - record = self.open(self.record_path) - except KeyError: - raise WheelError('Missing {} file'.format(self.record_path)) - - with record: - for line in record: - line = line.decode('utf-8') - path, hash_sum, size = line.rsplit(u',', 2) - if hash_sum: - algorithm, hash_sum = hash_sum.split(u'=') - try: - hashlib.new(algorithm) - except ValueError: - raise WheelError('Unsupported hash algorithm: {}'.format(algorithm)) - - if algorithm.lower() in {'md5', 'sha1'}: - raise WheelError( - 'Weak hash algorithm ({}) is not permitted by PEP 427' - .format(algorithm)) - - self._file_hashes[path] = ( - algorithm, urlsafe_b64decode(hash_sum.encode('ascii'))) - - def open(self, name_or_info, mode="r", pwd=None): - def _update_crc(newdata, eof=None): - if eof is None: - eof = ef._eof - update_crc_orig(newdata) - else: # Python 2 - update_crc_orig(newdata, eof) - - running_hash.update(newdata) - if eof and running_hash.digest() != expected_hash: - raise WheelError("Hash mismatch for file '{}'".format(native(ef_name))) - - ef = ZipFile.open(self, name_or_info, mode, pwd) - ef_name = as_unicode(name_or_info.filename if isinstance(name_or_info, ZipInfo) - else name_or_info) - if mode == 'r' and not ef_name.endswith('/'): - if ef_name not in self._file_hashes: - raise WheelError("No hash found for file '{}'".format(native(ef_name))) - - algorithm, expected_hash = self._file_hashes[ef_name] - if expected_hash is not None: - # Monkey patch the _update_crc method to also check for the hash from RECORD - running_hash = hashlib.new(algorithm) - update_crc_orig, ef._update_crc = ef._update_crc, _update_crc - - return ef - - def write_files(self, base_dir): - logger.info("creating '%s' and adding '%s' to it", self.filename, base_dir) - deferred = [] - for root, dirnames, filenames in os.walk(base_dir): - # Sort the directory names so that `os.walk` will walk them in a - # defined order on the next iteration. - dirnames.sort() - for name in sorted(filenames): - path = os.path.normpath(os.path.join(root, name)) - if os.path.isfile(path): - arcname = os.path.relpath(path, base_dir).replace(os.path.sep, '/') - if arcname == self.record_path: - pass - elif root.endswith('.dist-info'): - deferred.append((path, arcname)) - else: - self.write(path, arcname) - - deferred.sort() - for path, arcname in deferred: - self.write(path, arcname) - - def write(self, filename, arcname=None, compress_type=None): - with open(filename, 'rb') as f: - st = os.fstat(f.fileno()) - data = f.read() - - zinfo = ZipInfo(arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)) - zinfo.external_attr = (stat.S_IMODE(st.st_mode) | stat.S_IFMT(st.st_mode)) << 16 - zinfo.compress_type = compress_type or self.compression - self.writestr(zinfo, data, compress_type) - - def writestr(self, zinfo_or_arcname, bytes, compress_type=None): - ZipFile.writestr(self, zinfo_or_arcname, bytes, compress_type) - fname = (zinfo_or_arcname.filename if isinstance(zinfo_or_arcname, ZipInfo) - else zinfo_or_arcname) - logger.info("adding '%s'", fname) - if fname != self.record_path: - hash_ = self._default_algorithm(bytes) - self._file_hashes[fname] = hash_.name, native(urlsafe_b64encode(hash_.digest())) - self._file_sizes[fname] = len(bytes) - - def close(self): - # Write RECORD - if self.fp is not None and self.mode == 'w' and self._file_hashes: - data = StringIO() - writer = csv.writer(data, delimiter=',', quotechar='"', lineterminator='\n') - writer.writerows(( - ( - fname, - algorithm + "=" + hash_, - self._file_sizes[fname] - ) - for fname, (algorithm, hash_) in self._file_hashes.items() - )) - writer.writerow((format(self.record_path), "", "")) - zinfo = ZipInfo(native(self.record_path), date_time=get_zipinfo_datetime()) - zinfo.compress_type = self.compression - zinfo.external_attr = 0o664 << 16 - self.writestr(zinfo, as_bytes(data.getvalue())) - - ZipFile.close(self) diff --git a/experiment/simulation/backend/venv/lib/python3.7/site.py b/experiment/simulation/backend/venv/lib/python3.7/site.py deleted file mode 100644 index ef1cd1a..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/site.py +++ /dev/null @@ -1,829 +0,0 @@ -"""Append module search paths for third-party packages to sys.path. - -**************************************************************** -* This module is automatically imported during initialization. * -**************************************************************** - -In earlier versions of Python (up to 1.5a3), scripts or modules that -needed to use site-specific modules would place ``import site'' -somewhere near the top of their code. Because of the automatic -import, this is no longer necessary (but code that does it still -works). - -This will append site-specific paths to the module search path. On -Unix, it starts with sys.prefix and sys.exec_prefix (if different) and -appends lib/python/site-packages as well as lib/site-python. -It also supports the Debian convention of -lib/python/dist-packages. On other platforms (mainly Mac and -Windows), it uses just sys.prefix (and sys.exec_prefix, if different, -but this is unlikely). The resulting directories, if they exist, are -appended to sys.path, and also inspected for path configuration files. - -FOR DEBIAN, this sys.path is augmented with directories in /usr/local. -Local addons go into /usr/local/lib/python/site-packages -(resp. /usr/local/lib/site-python), Debian addons install into -/usr/{lib,share}/python/dist-packages. - -A path configuration file is a file whose name has the form -.pth; its contents are additional directories (one per line) -to be added to sys.path. Non-existing directories (or -non-directories) are never added to sys.path; no directory is added to -sys.path more than once. Blank lines and lines beginning with -'#' are skipped. Lines starting with 'import' are executed. - -For example, suppose sys.prefix and sys.exec_prefix are set to -/usr/local and there is a directory /usr/local/lib/python2.X/site-packages -with three subdirectories, foo, bar and spam, and two path -configuration files, foo.pth and bar.pth. Assume foo.pth contains the -following: - - # foo package configuration - foo - bar - bletch - -and bar.pth contains: - - # bar package configuration - bar - -Then the following directories are added to sys.path, in this order: - - /usr/local/lib/python2.X/site-packages/bar - /usr/local/lib/python2.X/site-packages/foo - -Note that bletch is omitted because it doesn't exist; bar precedes foo -because bar.pth comes alphabetically before foo.pth; and spam is -omitted because it is not mentioned in either path configuration file. - -After these path manipulations, an attempt is made to import a module -named sitecustomize, which can perform arbitrary additional -site-specific customizations. If this import fails with an -ImportError exception, it is silently ignored. - -""" - -import os -import sys - -try: - import __builtin__ as builtins -except ImportError: - import builtins -try: - set -except NameError: - from sets import Set as set - -# Prefixes for site-packages; add additional prefixes like /usr/local here -PREFIXES = [sys.prefix, sys.exec_prefix] -# Enable per user site-packages directory -# set it to False to disable the feature or True to force the feature -ENABLE_USER_SITE = None -# for distutils.commands.install -USER_SITE = None -USER_BASE = None - -_is_64bit = (getattr(sys, "maxsize", None) or getattr(sys, "maxint")) > 2 ** 32 -_is_pypy = hasattr(sys, "pypy_version_info") - - -def makepath(*paths): - dir = os.path.join(*paths) - dir = os.path.abspath(dir) - return dir, os.path.normcase(dir) - - -def abs__file__(): - """Set all module' __file__ attribute to an absolute path""" - for m in sys.modules.values(): - f = getattr(m, "__file__", None) - if f is None: - continue - m.__file__ = os.path.abspath(f) - - -def removeduppaths(): - """ Remove duplicate entries from sys.path along with making them - absolute""" - # This ensures that the initial path provided by the interpreter contains - # only absolute pathnames, even if we're running from the build directory. - L = [] - known_paths = set() - for dir in sys.path: - # Filter out duplicate paths (on case-insensitive file systems also - # if they only differ in case); turn relative paths into absolute - # paths. - dir, dircase = makepath(dir) - if not dircase in known_paths: - L.append(dir) - known_paths.add(dircase) - sys.path[:] = L - return known_paths - - -# XXX This should not be part of site.py, since it is needed even when -# using the -S option for Python. See http://www.python.org/sf/586680 -def addbuilddir(): - """Append ./build/lib. in case we're running in the build dir - (especially for Guido :-)""" - from distutils.util import get_platform - - s = "build/lib.{}-{}.{}".format(get_platform(), *sys.version_info) - if hasattr(sys, "gettotalrefcount"): - s += "-pydebug" - s = os.path.join(os.path.dirname(sys.path[-1]), s) - sys.path.append(s) - - -def _init_pathinfo(): - """Return a set containing all existing directory entries from sys.path""" - d = set() - for dir in sys.path: - try: - if os.path.isdir(dir): - dir, dircase = makepath(dir) - d.add(dircase) - except TypeError: - continue - return d - - -def addpackage(sitedir, name, known_paths): - """Add a new path to known_paths by combining sitedir and 'name' or execute - sitedir if it starts with 'import'""" - if known_paths is None: - _init_pathinfo() - reset = 1 - else: - reset = 0 - fullname = os.path.join(sitedir, name) - try: - f = open(fullname, "r") - except IOError: - return - try: - for line in f: - if line.startswith("#"): - continue - if line.startswith("import"): - exec(line) - continue - line = line.rstrip() - dir, dircase = makepath(sitedir, line) - if not dircase in known_paths and os.path.exists(dir): - sys.path.append(dir) - known_paths.add(dircase) - finally: - f.close() - if reset: - known_paths = None - return known_paths - - -def addsitedir(sitedir, known_paths=None): - """Add 'sitedir' argument to sys.path if missing and handle .pth files in - 'sitedir'""" - if known_paths is None: - known_paths = _init_pathinfo() - reset = 1 - else: - reset = 0 - sitedir, sitedircase = makepath(sitedir) - if not sitedircase in known_paths: - sys.path.append(sitedir) # Add path component - try: - names = os.listdir(sitedir) - except os.error: - return - names.sort() - for name in names: - if name.endswith(os.extsep + "pth"): - addpackage(sitedir, name, known_paths) - if reset: - known_paths = None - return known_paths - - -def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): - """Add site-packages (and possibly site-python) to sys.path""" - prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] - if exec_prefix != sys_prefix: - prefixes.append(os.path.join(exec_prefix, "local")) - - for prefix in prefixes: - if prefix: - if sys.platform in ("os2emx", "riscos"): - sitedirs = [os.path.join(prefix, "Lib", "site-packages")] - elif _is_pypy: - sitedirs = [os.path.join(prefix, "site-packages")] - elif sys.platform == "darwin" and prefix == sys_prefix: - - if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python - - sitedirs = [ - os.path.join("/Library/Python", "{}.{}".format(*sys.version_info), "site-packages"), - os.path.join(prefix, "Extras", "lib", "python"), - ] - - else: # any other Python distros on OSX work this way - sitedirs = [os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "site-packages")] - - elif os.sep == "/": - sitedirs = [ - os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "site-packages"), - os.path.join(prefix, "lib", "site-python"), - os.path.join(prefix, "python{}.{}".format(*sys.version_info), "lib-dynload"), - ] - lib64_dir = os.path.join(prefix, "lib64", "python{}.{}".format(*sys.version_info), "site-packages") - if os.path.exists(lib64_dir) and os.path.realpath(lib64_dir) not in [ - os.path.realpath(p) for p in sitedirs - ]: - if _is_64bit: - sitedirs.insert(0, lib64_dir) - else: - sitedirs.append(lib64_dir) - try: - # sys.getobjects only available in --with-pydebug build - sys.getobjects - sitedirs.insert(0, os.path.join(sitedirs[0], "debug")) - except AttributeError: - pass - # Debian-specific dist-packages directories: - sitedirs.append( - os.path.join(prefix, "local/lib", "python{}.{}".format(*sys.version_info), "dist-packages") - ) - if sys.version_info[0] == 2: - sitedirs.append( - os.path.join(prefix, "lib", "python{}.{}".format(*sys.version_info), "dist-packages") - ) - else: - sitedirs.append( - os.path.join(prefix, "lib", "python{}".format(sys.version_info[0]), "dist-packages") - ) - sitedirs.append(os.path.join(prefix, "lib", "dist-python")) - else: - sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] - if sys.platform == "darwin": - # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too - if "Python.framework" in prefix or "Python3.framework" in prefix: - home = os.environ.get("HOME") - if home: - sitedirs.append( - os.path.join(home, "Library", "Python", "{}.{}".format(*sys.version_info), "site-packages") - ) - for sitedir in sitedirs: - if os.path.isdir(sitedir): - addsitedir(sitedir, known_paths) - return None - - -def check_enableusersite(): - """Check if user site directory is safe for inclusion - - The function tests for the command line flag (including environment var), - process uid/gid equal to effective uid/gid. - - None: Disabled for security reasons - False: Disabled by user (command line option) - True: Safe and enabled - """ - if hasattr(sys, "flags") and getattr(sys.flags, "no_user_site", False): - return False - - if hasattr(os, "getuid") and hasattr(os, "geteuid"): - # check process uid == effective uid - if os.geteuid() != os.getuid(): - return None - if hasattr(os, "getgid") and hasattr(os, "getegid"): - # check process gid == effective gid - if os.getegid() != os.getgid(): - return None - - return True - - -def addusersitepackages(known_paths): - """Add a per user site-package to sys.path - - Each user has its own python directory with site-packages in the - home directory. - - USER_BASE is the root directory for all Python versions - - USER_SITE is the user specific site-packages directory - - USER_SITE/.. can be used for data. - """ - global USER_BASE, USER_SITE, ENABLE_USER_SITE - env_base = os.environ.get("PYTHONUSERBASE", None) - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - # if sys.platform in ('os2emx', 'riscos'): - # # Don't know what to put here - # USER_BASE = '' - # USER_SITE = '' - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - if env_base: - USER_BASE = env_base - else: - USER_BASE = joinuser(base, "Python") - USER_SITE = os.path.join(USER_BASE, "Python{}{}".format(*sys.version_info), "site-packages") - else: - if env_base: - USER_BASE = env_base - else: - USER_BASE = joinuser("~", ".local") - USER_SITE = os.path.join(USER_BASE, "lib", "python{}.{}".format(*sys.version_info), "site-packages") - - if ENABLE_USER_SITE and os.path.isdir(USER_SITE): - addsitedir(USER_SITE, known_paths) - if ENABLE_USER_SITE: - for dist_libdir in ("lib", "local/lib"): - user_site = os.path.join(USER_BASE, dist_libdir, "python{}.{}".format(*sys.version_info), "dist-packages") - if os.path.isdir(user_site): - addsitedir(user_site, known_paths) - return known_paths - - -def setBEGINLIBPATH(): - """The OS/2 EMX port has optional extension modules that do double duty - as DLLs (and must use the .DLL file extension) for other extensions. - The library search path needs to be amended so these will be found - during module import. Use BEGINLIBPATH so that these are at the start - of the library search path. - - """ - dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") - libpath = os.environ["BEGINLIBPATH"].split(";") - if libpath[-1]: - libpath.append(dllpath) - else: - libpath[-1] = dllpath - os.environ["BEGINLIBPATH"] = ";".join(libpath) - - -def setquit(): - """Define new built-ins 'quit' and 'exit'. - These are simply strings that display a hint on how to exit. - - """ - if os.sep == ":": - eof = "Cmd-Q" - elif os.sep == "\\": - eof = "Ctrl-Z plus Return" - else: - eof = "Ctrl-D (i.e. EOF)" - - class Quitter(object): - def __init__(self, name): - self.name = name - - def __repr__(self): - return "Use {}() or {} to exit".format(self.name, eof) - - def __call__(self, code=None): - # Shells like IDLE catch the SystemExit, but listen when their - # stdin wrapper is closed. - try: - sys.stdin.close() - except: - pass - raise SystemExit(code) - - builtins.quit = Quitter("quit") - builtins.exit = Quitter("exit") - - -class _Printer(object): - """interactive prompt objects for printing the license text, a list of - contributors and the copyright notice.""" - - MAXLINES = 23 - - def __init__(self, name, data, files=(), dirs=()): - self.__name = name - self.__data = data - self.__files = files - self.__dirs = dirs - self.__lines = None - - def __setup(self): - if self.__lines: - return - data = None - for dir in self.__dirs: - for filename in self.__files: - filename = os.path.join(dir, filename) - try: - fp = open(filename, "r") - data = fp.read() - fp.close() - break - except IOError: - pass - if data: - break - if not data: - data = self.__data - self.__lines = data.split("\n") - self.__linecnt = len(self.__lines) - - def __repr__(self): - self.__setup() - if len(self.__lines) <= self.MAXLINES: - return "\n".join(self.__lines) - else: - return "Type %s() to see the full %s text" % ((self.__name,) * 2) - - def __call__(self): - self.__setup() - prompt = "Hit Return for more, or q (and Return) to quit: " - lineno = 0 - while 1: - try: - for i in range(lineno, lineno + self.MAXLINES): - print(self.__lines[i]) - except IndexError: - break - else: - lineno += self.MAXLINES - key = None - while key is None: - try: - key = raw_input(prompt) - except NameError: - key = input(prompt) - if key not in ("", "q"): - key = None - if key == "q": - break - - -def setcopyright(): - """Set 'copyright' and 'credits' in __builtin__""" - builtins.copyright = _Printer("copyright", sys.copyright) - if _is_pypy: - builtins.credits = _Printer("credits", "PyPy is maintained by the PyPy developers: http://pypy.org/") - else: - builtins.credits = _Printer( - "credits", - """\ - Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands - for supporting Python development. See www.python.org for more information.""", - ) - here = os.path.dirname(os.__file__) - builtins.license = _Printer( - "license", - "See https://www.python.org/psf/license/", - ["LICENSE.txt", "LICENSE"], - [sys.prefix, os.path.join(here, os.pardir), here, os.curdir], - ) - - -class _Helper(object): - """Define the built-in 'help'. - This is a wrapper around pydoc.help (with a twist). - - """ - - def __repr__(self): - return "Type help() for interactive help, " "or help(object) for help about object." - - def __call__(self, *args, **kwds): - import pydoc - - return pydoc.help(*args, **kwds) - - -def sethelper(): - builtins.help = _Helper() - - -def aliasmbcs(): - """On Windows, some default encodings are not provided by Python, - while they are always available as "mbcs" in each locale. Make - them usable by aliasing to "mbcs" in such a case.""" - if sys.platform == "win32": - import locale, codecs - - enc = locale.getdefaultlocale()[1] - if enc.startswith("cp"): # "cp***" ? - try: - codecs.lookup(enc) - except LookupError: - import encodings - - encodings._cache[enc] = encodings._unknown - encodings.aliases.aliases[enc] = "mbcs" - - -def setencoding(): - """Set the string encoding used by the Unicode implementation. The - default is 'ascii', but if you're willing to experiment, you can - change this.""" - encoding = "ascii" # Default value set by _PyUnicode_Init() - if 0: - # Enable to support locale aware default string encodings. - import locale - - loc = locale.getdefaultlocale() - if loc[1]: - encoding = loc[1] - if 0: - # Enable to switch off string to Unicode coercion and implicit - # Unicode to string conversion. - encoding = "undefined" - if encoding != "ascii": - # On Non-Unicode builds this will raise an AttributeError... - sys.setdefaultencoding(encoding) # Needs Python Unicode build ! - - -def execsitecustomize(): - """Run custom site specific code, if available.""" - try: - import sitecustomize - except ImportError: - pass - - -def virtual_install_main_packages(): - f = open(os.path.join(os.path.dirname(__file__), "orig-prefix.txt")) - sys.real_prefix = f.read().strip() - f.close() - pos = 2 - hardcoded_relative_dirs = [] - if sys.path[0] == "": - pos += 1 - if _is_pypy: - if sys.version_info > (3, 2): - cpyver = "%d" % sys.version_info[0] - elif sys.pypy_version_info >= (1, 5): - cpyver = "%d.%d" % sys.version_info[:2] - else: - cpyver = "%d.%d.%d" % sys.version_info[:3] - paths = [os.path.join(sys.real_prefix, "lib_pypy"), os.path.join(sys.real_prefix, "lib-python", cpyver)] - if sys.pypy_version_info < (1, 9): - paths.insert(1, os.path.join(sys.real_prefix, "lib-python", "modified-%s" % cpyver)) - hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below - # - # This is hardcoded in the Python executable, but relative to sys.prefix: - for path in paths[:]: - plat_path = os.path.join(path, "plat-%s" % sys.platform) - if os.path.exists(plat_path): - paths.append(plat_path) - elif sys.platform == "win32": - paths = [os.path.join(sys.real_prefix, "Lib"), os.path.join(sys.real_prefix, "DLLs")] - else: - paths = [os.path.join(sys.real_prefix, "lib", "python{}.{}".format(*sys.version_info))] - hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below - lib64_path = os.path.join(sys.real_prefix, "lib64", "python{}.{}".format(*sys.version_info)) - if os.path.exists(lib64_path): - if _is_64bit: - paths.insert(0, lib64_path) - else: - paths.append(lib64_path) - # This is hardcoded in the Python executable, but relative to - # sys.prefix. Debian change: we need to add the multiarch triplet - # here, which is where the real stuff lives. As per PEP 421, in - # Python 3.3+, this lives in sys.implementation, while in Python 2.7 - # it lives in sys. - try: - arch = getattr(sys, "implementation", sys)._multiarch - except AttributeError: - # This is a non-multiarch aware Python. Fallback to the old way. - arch = sys.platform - plat_path = os.path.join(sys.real_prefix, "lib", "python{}.{}".format(*sys.version_info), "plat-%s" % arch) - if os.path.exists(plat_path): - paths.append(plat_path) - # This is hardcoded in the Python executable, but - # relative to sys.prefix, so we have to fix up: - for path in list(paths): - tk_dir = os.path.join(path, "lib-tk") - if os.path.exists(tk_dir): - paths.append(tk_dir) - - # These are hardcoded in the Apple's Python executable, - # but relative to sys.prefix, so we have to fix them up: - if sys.platform == "darwin": - hardcoded_paths = [ - os.path.join(relative_dir, module) - for relative_dir in hardcoded_relative_dirs - for module in ("plat-darwin", "plat-mac", "plat-mac/lib-scriptpackages") - ] - - for path in hardcoded_paths: - if os.path.exists(path): - paths.append(path) - - sys.path.extend(paths) - - -def force_global_eggs_after_local_site_packages(): - """ - Force easy_installed eggs in the global environment to get placed - in sys.path after all packages inside the virtualenv. This - maintains the "least surprise" result that packages in the - virtualenv always mask global packages, never the other way - around. - - """ - egginsert = getattr(sys, "__egginsert", 0) - for i, path in enumerate(sys.path): - if i > egginsert and path.startswith(sys.prefix): - egginsert = i - sys.__egginsert = egginsert + 1 - - -def virtual_addsitepackages(known_paths): - force_global_eggs_after_local_site_packages() - return addsitepackages(known_paths, sys_prefix=sys.real_prefix) - - -def execusercustomize(): - """Run custom user specific code, if available.""" - try: - import usercustomize - except ImportError: - pass - - -def enablerlcompleter(): - """Enable default readline configuration on interactive prompts, by - registering a sys.__interactivehook__. - If the readline module can be imported, the hook will set the Tab key - as completion key and register ~/.python_history as history file. - This can be overridden in the sitecustomize or usercustomize module, - or in a PYTHONSTARTUP file. - """ - - def register_readline(): - import atexit - - try: - import readline - import rlcompleter - except ImportError: - return - - # Reading the initialization (config) file may not be enough to set a - # completion key, so we set one first and then read the file. - readline_doc = getattr(readline, "__doc__", "") - if readline_doc is not None and "libedit" in readline_doc: - readline.parse_and_bind("bind ^I rl_complete") - else: - readline.parse_and_bind("tab: complete") - - try: - readline.read_init_file() - except OSError: - # An OSError here could have many causes, but the most likely one - # is that there's no .inputrc file (or .editrc file in the case of - # Mac OS X + libedit) in the expected location. In that case, we - # want to ignore the exception. - pass - - if readline.get_current_history_length() == 0: - # If no history was loaded, default to .python_history. - # The guard is necessary to avoid doubling history size at - # each interpreter exit when readline was already configured - # through a PYTHONSTARTUP hook, see: - # http://bugs.python.org/issue5845#msg198636 - history = os.path.join(os.path.expanduser("~"), ".python_history") - try: - readline.read_history_file(history) - except OSError: - pass - - def write_history(): - try: - readline.write_history_file(history) - except (FileNotFoundError, PermissionError): - # home directory does not exist or is not writable - # https://bugs.python.org/issue19891 - pass - - atexit.register(write_history) - - sys.__interactivehook__ = register_readline - - -if _is_pypy: - - def import_builtin_stuff(): - """PyPy specific: some built-in modules should be pre-imported because - some programs expect them to be in sys.modules on startup. This is ported - from PyPy's site.py. - """ - import encodings - - if "exceptions" in sys.builtin_module_names: - import exceptions - - if "zipimport" in sys.builtin_module_names: - import zipimport - - -def main(): - global ENABLE_USER_SITE - virtual_install_main_packages() - if _is_pypy: - import_builtin_stuff() - abs__file__() - paths_in_sys = removeduppaths() - if os.name == "posix" and sys.path and os.path.basename(sys.path[-1]) == "Modules": - addbuilddir() - GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), "no-global-site-packages.txt")) - if not GLOBAL_SITE_PACKAGES: - ENABLE_USER_SITE = False - if ENABLE_USER_SITE is None: - ENABLE_USER_SITE = check_enableusersite() - paths_in_sys = addsitepackages(paths_in_sys) - paths_in_sys = addusersitepackages(paths_in_sys) - if GLOBAL_SITE_PACKAGES: - paths_in_sys = virtual_addsitepackages(paths_in_sys) - if sys.platform == "os2emx": - setBEGINLIBPATH() - setquit() - setcopyright() - sethelper() - if sys.version_info[0] == 3: - enablerlcompleter() - aliasmbcs() - setencoding() - execsitecustomize() - if ENABLE_USER_SITE: - execusercustomize() - # Remove sys.setdefaultencoding() so that users cannot change the - # encoding after initialization. The test for presence is needed when - # this module is run as a script, because this code is executed twice. - if hasattr(sys, "setdefaultencoding"): - del sys.setdefaultencoding - - -main() - - -def _script(): - help = """\ - %s [--user-base] [--user-site] - - Without arguments print some useful information - With arguments print the value of USER_BASE and/or USER_SITE separated - by '%s'. - - Exit codes with --user-base or --user-site: - 0 - user site directory is enabled - 1 - user site directory is disabled by user - 2 - uses site directory is disabled by super user - or for security reasons - >2 - unknown error - """ - args = sys.argv[1:] - if not args: - print("sys.path = [") - for dir in sys.path: - print(" {!r},".format(dir)) - print("]") - - def exists(path): - if os.path.isdir(path): - return "exists" - else: - return "doesn't exist" - - print("USER_BASE: {!r} ({})".format(USER_BASE, exists(USER_BASE))) - print("USER_SITE: {!r} ({})".format(USER_SITE, exists(USER_SITE))) - print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) - sys.exit(0) - - buffer = [] - if "--user-base" in args: - buffer.append(USER_BASE) - if "--user-site" in args: - buffer.append(USER_SITE) - - if buffer: - print(os.pathsep.join(buffer)) - if ENABLE_USER_SITE: - sys.exit(0) - elif ENABLE_USER_SITE is False: - sys.exit(1) - elif ENABLE_USER_SITE is None: - sys.exit(2) - else: - sys.exit(3) - else: - import textwrap - - print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) - sys.exit(10) - - -if __name__ == "__main__": - _script() diff --git a/experiment/simulation/backend/venv/lib/python3.7/sre_compile.py b/experiment/simulation/backend/venv/lib/python3.7/sre_compile.py deleted file mode 100644 index e5216b7..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/sre_compile.py +++ /dev/null @@ -1,784 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# convert template to internal format -# -# Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. -# -# See the sre.py file for information on usage and redistribution. -# - -"""Internal support module for sre""" - -import _sre -import sre_parse -from sre_constants import * - -assert _sre.MAGIC == MAGIC, "SRE module mismatch" - -_LITERAL_CODES = {LITERAL, NOT_LITERAL} -_REPEATING_CODES = {REPEAT, MIN_REPEAT, MAX_REPEAT} -_SUCCESS_CODES = {SUCCESS, FAILURE} -_ASSERT_CODES = {ASSERT, ASSERT_NOT} -_UNIT_CODES = _LITERAL_CODES | {ANY, IN} - -# Sets of lowercase characters which have the same uppercase. -_equivalences = ( - # LATIN SMALL LETTER I, LATIN SMALL LETTER DOTLESS I - (0x69, 0x131), # iı - # LATIN SMALL LETTER S, LATIN SMALL LETTER LONG S - (0x73, 0x17f), # sſ - # MICRO SIGN, GREEK SMALL LETTER MU - (0xb5, 0x3bc), # µμ - # COMBINING GREEK YPOGEGRAMMENI, GREEK SMALL LETTER IOTA, GREEK PROSGEGRAMMENI - (0x345, 0x3b9, 0x1fbe), # \u0345ιι - # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS, GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA - (0x390, 0x1fd3), # ΐΐ - # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS, GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA - (0x3b0, 0x1fe3), # ΰΰ - # GREEK SMALL LETTER BETA, GREEK BETA SYMBOL - (0x3b2, 0x3d0), # βϐ - # GREEK SMALL LETTER EPSILON, GREEK LUNATE EPSILON SYMBOL - (0x3b5, 0x3f5), # εϵ - # GREEK SMALL LETTER THETA, GREEK THETA SYMBOL - (0x3b8, 0x3d1), # θϑ - # GREEK SMALL LETTER KAPPA, GREEK KAPPA SYMBOL - (0x3ba, 0x3f0), # κϰ - # GREEK SMALL LETTER PI, GREEK PI SYMBOL - (0x3c0, 0x3d6), # πϖ - # GREEK SMALL LETTER RHO, GREEK RHO SYMBOL - (0x3c1, 0x3f1), # ρϱ - # GREEK SMALL LETTER FINAL SIGMA, GREEK SMALL LETTER SIGMA - (0x3c2, 0x3c3), # ςσ - # GREEK SMALL LETTER PHI, GREEK PHI SYMBOL - (0x3c6, 0x3d5), # φϕ - # LATIN SMALL LETTER S WITH DOT ABOVE, LATIN SMALL LETTER LONG S WITH DOT ABOVE - (0x1e61, 0x1e9b), # ṡẛ - # LATIN SMALL LIGATURE LONG S T, LATIN SMALL LIGATURE ST - (0xfb05, 0xfb06), # ſtst -) - -# Maps the lowercase code to lowercase codes which have the same uppercase. -_ignorecase_fixes = {i: tuple(j for j in t if i != j) - for t in _equivalences for i in t} - -def _combine_flags(flags, add_flags, del_flags, - TYPE_FLAGS=sre_parse.TYPE_FLAGS): - if add_flags & TYPE_FLAGS: - flags &= ~TYPE_FLAGS - return (flags | add_flags) & ~del_flags - -def _compile(code, pattern, flags): - # internal: compile a (sub)pattern - emit = code.append - _len = len - LITERAL_CODES = _LITERAL_CODES - REPEATING_CODES = _REPEATING_CODES - SUCCESS_CODES = _SUCCESS_CODES - ASSERT_CODES = _ASSERT_CODES - iscased = None - tolower = None - fixes = None - if flags & SRE_FLAG_IGNORECASE and not flags & SRE_FLAG_LOCALE: - if flags & SRE_FLAG_UNICODE and not flags & SRE_FLAG_ASCII: - iscased = _sre.unicode_iscased - tolower = _sre.unicode_tolower - fixes = _ignorecase_fixes - else: - iscased = _sre.ascii_iscased - tolower = _sre.ascii_tolower - for op, av in pattern: - if op in LITERAL_CODES: - if not flags & SRE_FLAG_IGNORECASE: - emit(op) - emit(av) - elif flags & SRE_FLAG_LOCALE: - emit(OP_LOCALE_IGNORE[op]) - emit(av) - elif not iscased(av): - emit(op) - emit(av) - else: - lo = tolower(av) - if not fixes: # ascii - emit(OP_IGNORE[op]) - emit(lo) - elif lo not in fixes: - emit(OP_UNICODE_IGNORE[op]) - emit(lo) - else: - emit(IN_UNI_IGNORE) - skip = _len(code); emit(0) - if op is NOT_LITERAL: - emit(NEGATE) - for k in (lo,) + fixes[lo]: - emit(LITERAL) - emit(k) - emit(FAILURE) - code[skip] = _len(code) - skip - elif op is IN: - charset, hascased = _optimize_charset(av, iscased, tolower, fixes) - if flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE: - emit(IN_LOC_IGNORE) - elif not hascased: - emit(IN) - elif not fixes: # ascii - emit(IN_IGNORE) - else: - emit(IN_UNI_IGNORE) - skip = _len(code); emit(0) - _compile_charset(charset, flags, code) - code[skip] = _len(code) - skip - elif op is ANY: - if flags & SRE_FLAG_DOTALL: - emit(ANY_ALL) - else: - emit(ANY) - elif op in REPEATING_CODES: - if flags & SRE_FLAG_TEMPLATE: - raise error("internal: unsupported template operator %r" % (op,)) - if _simple(av[2]): - if op is MAX_REPEAT: - emit(REPEAT_ONE) - else: - emit(MIN_REPEAT_ONE) - skip = _len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - emit(SUCCESS) - code[skip] = _len(code) - skip - else: - emit(REPEAT) - skip = _len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - code[skip] = _len(code) - skip - if op is MAX_REPEAT: - emit(MAX_UNTIL) - else: - emit(MIN_UNTIL) - elif op is SUBPATTERN: - group, add_flags, del_flags, p = av - if group: - emit(MARK) - emit((group-1)*2) - # _compile_info(code, p, _combine_flags(flags, add_flags, del_flags)) - _compile(code, p, _combine_flags(flags, add_flags, del_flags)) - if group: - emit(MARK) - emit((group-1)*2+1) - elif op in SUCCESS_CODES: - emit(op) - elif op in ASSERT_CODES: - emit(op) - skip = _len(code); emit(0) - if av[0] >= 0: - emit(0) # look ahead - else: - lo, hi = av[1].getwidth() - if lo != hi: - raise error("look-behind requires fixed-width pattern") - emit(lo) # look behind - _compile(code, av[1], flags) - emit(SUCCESS) - code[skip] = _len(code) - skip - elif op is CALL: - emit(op) - skip = _len(code); emit(0) - _compile(code, av, flags) - emit(SUCCESS) - code[skip] = _len(code) - skip - elif op is AT: - emit(op) - if flags & SRE_FLAG_MULTILINE: - av = AT_MULTILINE.get(av, av) - if flags & SRE_FLAG_LOCALE: - av = AT_LOCALE.get(av, av) - elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): - av = AT_UNICODE.get(av, av) - emit(av) - elif op is BRANCH: - emit(op) - tail = [] - tailappend = tail.append - for av in av[1]: - skip = _len(code); emit(0) - # _compile_info(code, av, flags) - _compile(code, av, flags) - emit(JUMP) - tailappend(_len(code)); emit(0) - code[skip] = _len(code) - skip - emit(FAILURE) # end of branch - for tail in tail: - code[tail] = _len(code) - tail - elif op is CATEGORY: - emit(op) - if flags & SRE_FLAG_LOCALE: - av = CH_LOCALE[av] - elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): - av = CH_UNICODE[av] - emit(av) - elif op is GROUPREF: - if not flags & SRE_FLAG_IGNORECASE: - emit(op) - elif flags & SRE_FLAG_LOCALE: - emit(GROUPREF_LOC_IGNORE) - elif not fixes: # ascii - emit(GROUPREF_IGNORE) - else: - emit(GROUPREF_UNI_IGNORE) - emit(av-1) - elif op is GROUPREF_EXISTS: - emit(op) - emit(av[0]-1) - skipyes = _len(code); emit(0) - _compile(code, av[1], flags) - if av[2]: - emit(JUMP) - skipno = _len(code); emit(0) - code[skipyes] = _len(code) - skipyes + 1 - _compile(code, av[2], flags) - code[skipno] = _len(code) - skipno - else: - code[skipyes] = _len(code) - skipyes + 1 - else: - raise error("internal: unsupported operand type %r" % (op,)) - -def _compile_charset(charset, flags, code): - # compile charset subprogram - emit = code.append - for op, av in charset: - emit(op) - if op is NEGATE: - pass - elif op is LITERAL: - emit(av) - elif op is RANGE or op is RANGE_UNI_IGNORE: - emit(av[0]) - emit(av[1]) - elif op is CHARSET: - code.extend(av) - elif op is BIGCHARSET: - code.extend(av) - elif op is CATEGORY: - if flags & SRE_FLAG_LOCALE: - emit(CH_LOCALE[av]) - elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): - emit(CH_UNICODE[av]) - else: - emit(av) - else: - raise error("internal: unsupported set operator %r" % (op,)) - emit(FAILURE) - -def _optimize_charset(charset, iscased=None, fixup=None, fixes=None): - # internal: optimize character set - out = [] - tail = [] - charmap = bytearray(256) - hascased = False - for op, av in charset: - while True: - try: - if op is LITERAL: - if fixup: - lo = fixup(av) - charmap[lo] = 1 - if fixes and lo in fixes: - for k in fixes[lo]: - charmap[k] = 1 - if not hascased and iscased(av): - hascased = True - else: - charmap[av] = 1 - elif op is RANGE: - r = range(av[0], av[1]+1) - if fixup: - if fixes: - for i in map(fixup, r): - charmap[i] = 1 - if i in fixes: - for k in fixes[i]: - charmap[k] = 1 - else: - for i in map(fixup, r): - charmap[i] = 1 - if not hascased: - hascased = any(map(iscased, r)) - else: - for i in r: - charmap[i] = 1 - elif op is NEGATE: - out.append((op, av)) - else: - tail.append((op, av)) - except IndexError: - if len(charmap) == 256: - # character set contains non-UCS1 character codes - charmap += b'\0' * 0xff00 - continue - # Character set contains non-BMP character codes. - if fixup: - hascased = True - # There are only two ranges of cased non-BMP characters: - # 10400-1044F (Deseret) and 118A0-118DF (Warang Citi), - # and for both ranges RANGE_UNI_IGNORE works. - if op is RANGE: - op = RANGE_UNI_IGNORE - tail.append((op, av)) - break - - # compress character map - runs = [] - q = 0 - while True: - p = charmap.find(1, q) - if p < 0: - break - if len(runs) >= 2: - runs = None - break - q = charmap.find(0, p) - if q < 0: - runs.append((p, len(charmap))) - break - runs.append((p, q)) - if runs is not None: - # use literal/range - for p, q in runs: - if q - p == 1: - out.append((LITERAL, p)) - else: - out.append((RANGE, (p, q - 1))) - out += tail - # if the case was changed or new representation is more compact - if hascased or len(out) < len(charset): - return out, hascased - # else original character set is good enough - return charset, hascased - - # use bitmap - if len(charmap) == 256: - data = _mk_bitmap(charmap) - out.append((CHARSET, data)) - out += tail - return out, hascased - - # To represent a big charset, first a bitmap of all characters in the - # set is constructed. Then, this bitmap is sliced into chunks of 256 - # characters, duplicate chunks are eliminated, and each chunk is - # given a number. In the compiled expression, the charset is - # represented by a 32-bit word sequence, consisting of one word for - # the number of different chunks, a sequence of 256 bytes (64 words) - # of chunk numbers indexed by their original chunk position, and a - # sequence of 256-bit chunks (8 words each). - - # Compression is normally good: in a typical charset, large ranges of - # Unicode will be either completely excluded (e.g. if only cyrillic - # letters are to be matched), or completely included (e.g. if large - # subranges of Kanji match). These ranges will be represented by - # chunks of all one-bits or all zero-bits. - - # Matching can be also done efficiently: the more significant byte of - # the Unicode character is an index into the chunk number, and the - # less significant byte is a bit index in the chunk (just like the - # CHARSET matching). - - charmap = bytes(charmap) # should be hashable - comps = {} - mapping = bytearray(256) - block = 0 - data = bytearray() - for i in range(0, 65536, 256): - chunk = charmap[i: i + 256] - if chunk in comps: - mapping[i // 256] = comps[chunk] - else: - mapping[i // 256] = comps[chunk] = block - block += 1 - data += chunk - data = _mk_bitmap(data) - data[0:0] = [block] + _bytes_to_codes(mapping) - out.append((BIGCHARSET, data)) - out += tail - return out, hascased - -_CODEBITS = _sre.CODESIZE * 8 -MAXCODE = (1 << _CODEBITS) - 1 -_BITS_TRANS = b'0' + b'1' * 255 -def _mk_bitmap(bits, _CODEBITS=_CODEBITS, _int=int): - s = bits.translate(_BITS_TRANS)[::-1] - return [_int(s[i - _CODEBITS: i], 2) - for i in range(len(s), 0, -_CODEBITS)] - -def _bytes_to_codes(b): - # Convert block indices to word array - a = memoryview(b).cast('I') - assert a.itemsize == _sre.CODESIZE - assert len(a) * a.itemsize == len(b) - return a.tolist() - -def _simple(p): - # check if this subpattern is a "simple" operator - if len(p) != 1: - return False - op, av = p[0] - if op is SUBPATTERN: - return av[0] is None and _simple(av[-1]) - return op in _UNIT_CODES - -def _generate_overlap_table(prefix): - """ - Generate an overlap table for the following prefix. - An overlap table is a table of the same size as the prefix which - informs about the potential self-overlap for each index in the prefix: - - if overlap[i] == 0, prefix[i:] can't overlap prefix[0:...] - - if overlap[i] == k with 0 < k <= i, prefix[i-k+1:i+1] overlaps with - prefix[0:k] - """ - table = [0] * len(prefix) - for i in range(1, len(prefix)): - idx = table[i - 1] - while prefix[i] != prefix[idx]: - if idx == 0: - table[i] = 0 - break - idx = table[idx - 1] - else: - table[i] = idx + 1 - return table - -def _get_iscased(flags): - if not flags & SRE_FLAG_IGNORECASE: - return None - elif flags & SRE_FLAG_UNICODE and not flags & SRE_FLAG_ASCII: - return _sre.unicode_iscased - else: - return _sre.ascii_iscased - -def _get_literal_prefix(pattern, flags): - # look for literal prefix - prefix = [] - prefixappend = prefix.append - prefix_skip = None - iscased = _get_iscased(flags) - for op, av in pattern.data: - if op is LITERAL: - if iscased and iscased(av): - break - prefixappend(av) - elif op is SUBPATTERN: - group, add_flags, del_flags, p = av - flags1 = _combine_flags(flags, add_flags, del_flags) - if flags1 & SRE_FLAG_IGNORECASE and flags1 & SRE_FLAG_LOCALE: - break - prefix1, prefix_skip1, got_all = _get_literal_prefix(p, flags1) - if prefix_skip is None: - if group is not None: - prefix_skip = len(prefix) - elif prefix_skip1 is not None: - prefix_skip = len(prefix) + prefix_skip1 - prefix.extend(prefix1) - if not got_all: - break - else: - break - else: - return prefix, prefix_skip, True - return prefix, prefix_skip, False - -def _get_charset_prefix(pattern, flags): - while True: - if not pattern.data: - return None - op, av = pattern.data[0] - if op is not SUBPATTERN: - break - group, add_flags, del_flags, pattern = av - flags = _combine_flags(flags, add_flags, del_flags) - if flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE: - return None - - iscased = _get_iscased(flags) - if op is LITERAL: - if iscased and iscased(av): - return None - return [(op, av)] - elif op is BRANCH: - charset = [] - charsetappend = charset.append - for p in av[1]: - if not p: - return None - op, av = p[0] - if op is LITERAL and not (iscased and iscased(av)): - charsetappend((op, av)) - else: - return None - return charset - elif op is IN: - charset = av - if iscased: - for op, av in charset: - if op is LITERAL: - if iscased(av): - return None - elif op is RANGE: - if av[1] > 0xffff: - return None - if any(map(iscased, range(av[0], av[1]+1))): - return None - return charset - return None - -def _compile_info(code, pattern, flags): - # internal: compile an info block. in the current version, - # this contains min/max pattern width, and an optional literal - # prefix or a character map - lo, hi = pattern.getwidth() - if hi > MAXCODE: - hi = MAXCODE - if lo == 0: - code.extend([INFO, 4, 0, lo, hi]) - return - # look for a literal prefix - prefix = [] - prefix_skip = 0 - charset = [] # not used - if not (flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE): - # look for literal prefix - prefix, prefix_skip, got_all = _get_literal_prefix(pattern, flags) - # if no prefix, look for charset prefix - if not prefix: - charset = _get_charset_prefix(pattern, flags) -## if prefix: -## print("*** PREFIX", prefix, prefix_skip) -## if charset: -## print("*** CHARSET", charset) - # add an info block - emit = code.append - emit(INFO) - skip = len(code); emit(0) - # literal flag - mask = 0 - if prefix: - mask = SRE_INFO_PREFIX - if prefix_skip is None and got_all: - mask = mask | SRE_INFO_LITERAL - elif charset: - mask = mask | SRE_INFO_CHARSET - emit(mask) - # pattern length - if lo < MAXCODE: - emit(lo) - else: - emit(MAXCODE) - prefix = prefix[:MAXCODE] - emit(min(hi, MAXCODE)) - # add literal prefix - if prefix: - emit(len(prefix)) # length - if prefix_skip is None: - prefix_skip = len(prefix) - emit(prefix_skip) # skip - code.extend(prefix) - # generate overlap table - code.extend(_generate_overlap_table(prefix)) - elif charset: - charset, hascased = _optimize_charset(charset) - assert not hascased - _compile_charset(charset, flags, code) - code[skip] = len(code) - skip - -def isstring(obj): - return isinstance(obj, (str, bytes)) - -def _code(p, flags): - - flags = p.pattern.flags | flags - code = [] - - # compile info block - _compile_info(code, p, flags) - - # compile the pattern - _compile(code, p.data, flags) - - code.append(SUCCESS) - - return code - -def _hex_code(code): - return '[%s]' % ', '.join('%#0*x' % (_sre.CODESIZE*2+2, x) for x in code) - -def dis(code): - import sys - - labels = set() - level = 0 - offset_width = len(str(len(code) - 1)) - - def dis_(start, end): - def print_(*args, to=None): - if to is not None: - labels.add(to) - args += ('(to %d)' % (to,),) - print('%*d%s ' % (offset_width, start, ':' if start in labels else '.'), - end=' '*(level-1)) - print(*args) - - def print_2(*args): - print(end=' '*(offset_width + 2*level)) - print(*args) - - nonlocal level - level += 1 - i = start - while i < end: - start = i - op = code[i] - i += 1 - op = OPCODES[op] - if op in (SUCCESS, FAILURE, ANY, ANY_ALL, - MAX_UNTIL, MIN_UNTIL, NEGATE): - print_(op) - elif op in (LITERAL, NOT_LITERAL, - LITERAL_IGNORE, NOT_LITERAL_IGNORE, - LITERAL_UNI_IGNORE, NOT_LITERAL_UNI_IGNORE, - LITERAL_LOC_IGNORE, NOT_LITERAL_LOC_IGNORE): - arg = code[i] - i += 1 - print_(op, '%#02x (%r)' % (arg, chr(arg))) - elif op is AT: - arg = code[i] - i += 1 - arg = str(ATCODES[arg]) - assert arg[:3] == 'AT_' - print_(op, arg[3:]) - elif op is CATEGORY: - arg = code[i] - i += 1 - arg = str(CHCODES[arg]) - assert arg[:9] == 'CATEGORY_' - print_(op, arg[9:]) - elif op in (IN, IN_IGNORE, IN_UNI_IGNORE, IN_LOC_IGNORE): - skip = code[i] - print_(op, skip, to=i+skip) - dis_(i+1, i+skip) - i += skip - elif op in (RANGE, RANGE_UNI_IGNORE): - lo, hi = code[i: i+2] - i += 2 - print_(op, '%#02x %#02x (%r-%r)' % (lo, hi, chr(lo), chr(hi))) - elif op is CHARSET: - print_(op, _hex_code(code[i: i + 256//_CODEBITS])) - i += 256//_CODEBITS - elif op is BIGCHARSET: - arg = code[i] - i += 1 - mapping = list(b''.join(x.to_bytes(_sre.CODESIZE, sys.byteorder) - for x in code[i: i + 256//_sre.CODESIZE])) - print_(op, arg, mapping) - i += 256//_sre.CODESIZE - level += 1 - for j in range(arg): - print_2(_hex_code(code[i: i + 256//_CODEBITS])) - i += 256//_CODEBITS - level -= 1 - elif op in (MARK, GROUPREF, GROUPREF_IGNORE, GROUPREF_UNI_IGNORE, - GROUPREF_LOC_IGNORE): - arg = code[i] - i += 1 - print_(op, arg) - elif op is JUMP: - skip = code[i] - print_(op, skip, to=i+skip) - i += 1 - elif op is BRANCH: - skip = code[i] - print_(op, skip, to=i+skip) - while skip: - dis_(i+1, i+skip) - i += skip - start = i - skip = code[i] - if skip: - print_('branch', skip, to=i+skip) - else: - print_(FAILURE) - i += 1 - elif op in (REPEAT, REPEAT_ONE, MIN_REPEAT_ONE): - skip, min, max = code[i: i+3] - if max == MAXREPEAT: - max = 'MAXREPEAT' - print_(op, skip, min, max, to=i+skip) - dis_(i+3, i+skip) - i += skip - elif op is GROUPREF_EXISTS: - arg, skip = code[i: i+2] - print_(op, arg, skip, to=i+skip) - i += 2 - elif op in (ASSERT, ASSERT_NOT): - skip, arg = code[i: i+2] - print_(op, skip, arg, to=i+skip) - dis_(i+2, i+skip) - i += skip - elif op is INFO: - skip, flags, min, max = code[i: i+4] - if max == MAXREPEAT: - max = 'MAXREPEAT' - print_(op, skip, bin(flags), min, max, to=i+skip) - start = i+4 - if flags & SRE_INFO_PREFIX: - prefix_len, prefix_skip = code[i+4: i+6] - print_2(' prefix_skip', prefix_skip) - start = i + 6 - prefix = code[start: start+prefix_len] - print_2(' prefix', - '[%s]' % ', '.join('%#02x' % x for x in prefix), - '(%r)' % ''.join(map(chr, prefix))) - start += prefix_len - print_2(' overlap', code[start: start+prefix_len]) - start += prefix_len - if flags & SRE_INFO_CHARSET: - level += 1 - print_2('in') - dis_(start, i+skip) - level -= 1 - i += skip - else: - raise ValueError(op) - - level -= 1 - - dis_(0, len(code)) - - -def compile(p, flags=0): - # internal: convert pattern list to internal format - - if isstring(p): - pattern = p - p = sre_parse.parse(p, flags) - else: - pattern = None - - code = _code(p, flags) - - if flags & SRE_FLAG_DEBUG: - print() - dis(code) - - # map in either direction - groupindex = p.pattern.groupdict - indexgroup = [None] * p.pattern.groups - for k, i in groupindex.items(): - indexgroup[i] = k - - return _sre.compile( - pattern, flags | p.pattern.flags, code, - p.pattern.groups-1, - groupindex, tuple(indexgroup) - ) diff --git a/experiment/simulation/backend/venv/lib/python3.7/sre_constants.py b/experiment/simulation/backend/venv/lib/python3.7/sre_constants.py deleted file mode 100644 index 13deb00..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/sre_constants.py +++ /dev/null @@ -1,261 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# various symbols used by the regular expression engine. -# run this script to update the _sre include files! -# -# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. -# -# See the sre.py file for information on usage and redistribution. -# - -"""Internal support module for sre""" - -# update when constants are added or removed - -MAGIC = 20171005 - -from _sre import MAXREPEAT, MAXGROUPS - -# SRE standard exception (access as sre.error) -# should this really be here? - -class error(Exception): - """Exception raised for invalid regular expressions. - - Attributes: - - msg: The unformatted error message - pattern: The regular expression pattern - pos: The index in the pattern where compilation failed (may be None) - lineno: The line corresponding to pos (may be None) - colno: The column corresponding to pos (may be None) - """ - - __module__ = 're' - - def __init__(self, msg, pattern=None, pos=None): - self.msg = msg - self.pattern = pattern - self.pos = pos - if pattern is not None and pos is not None: - msg = '%s at position %d' % (msg, pos) - if isinstance(pattern, str): - newline = '\n' - else: - newline = b'\n' - self.lineno = pattern.count(newline, 0, pos) + 1 - self.colno = pos - pattern.rfind(newline, 0, pos) - if newline in pattern: - msg = '%s (line %d, column %d)' % (msg, self.lineno, self.colno) - else: - self.lineno = self.colno = None - super().__init__(msg) - - -class _NamedIntConstant(int): - def __new__(cls, value, name): - self = super(_NamedIntConstant, cls).__new__(cls, value) - self.name = name - return self - - def __str__(self): - return self.name - - __repr__ = __str__ - -MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT') - -def _makecodes(names): - names = names.strip().split() - items = [_NamedIntConstant(i, name) for i, name in enumerate(names)] - globals().update({item.name: item for item in items}) - return items - -# operators -# failure=0 success=1 (just because it looks better that way :-) -OPCODES = _makecodes(""" - FAILURE SUCCESS - - ANY ANY_ALL - ASSERT ASSERT_NOT - AT - BRANCH - CALL - CATEGORY - CHARSET BIGCHARSET - GROUPREF GROUPREF_EXISTS - IN - INFO - JUMP - LITERAL - MARK - MAX_UNTIL - MIN_UNTIL - NOT_LITERAL - NEGATE - RANGE - REPEAT - REPEAT_ONE - SUBPATTERN - MIN_REPEAT_ONE - - GROUPREF_IGNORE - IN_IGNORE - LITERAL_IGNORE - NOT_LITERAL_IGNORE - - GROUPREF_LOC_IGNORE - IN_LOC_IGNORE - LITERAL_LOC_IGNORE - NOT_LITERAL_LOC_IGNORE - - GROUPREF_UNI_IGNORE - IN_UNI_IGNORE - LITERAL_UNI_IGNORE - NOT_LITERAL_UNI_IGNORE - RANGE_UNI_IGNORE - - MIN_REPEAT MAX_REPEAT -""") -del OPCODES[-2:] # remove MIN_REPEAT and MAX_REPEAT - -# positions -ATCODES = _makecodes(""" - AT_BEGINNING AT_BEGINNING_LINE AT_BEGINNING_STRING - AT_BOUNDARY AT_NON_BOUNDARY - AT_END AT_END_LINE AT_END_STRING - - AT_LOC_BOUNDARY AT_LOC_NON_BOUNDARY - - AT_UNI_BOUNDARY AT_UNI_NON_BOUNDARY -""") - -# categories -CHCODES = _makecodes(""" - CATEGORY_DIGIT CATEGORY_NOT_DIGIT - CATEGORY_SPACE CATEGORY_NOT_SPACE - CATEGORY_WORD CATEGORY_NOT_WORD - CATEGORY_LINEBREAK CATEGORY_NOT_LINEBREAK - - CATEGORY_LOC_WORD CATEGORY_LOC_NOT_WORD - - CATEGORY_UNI_DIGIT CATEGORY_UNI_NOT_DIGIT - CATEGORY_UNI_SPACE CATEGORY_UNI_NOT_SPACE - CATEGORY_UNI_WORD CATEGORY_UNI_NOT_WORD - CATEGORY_UNI_LINEBREAK CATEGORY_UNI_NOT_LINEBREAK -""") - - -# replacement operations for "ignore case" mode -OP_IGNORE = { - LITERAL: LITERAL_IGNORE, - NOT_LITERAL: NOT_LITERAL_IGNORE, -} - -OP_LOCALE_IGNORE = { - LITERAL: LITERAL_LOC_IGNORE, - NOT_LITERAL: NOT_LITERAL_LOC_IGNORE, -} - -OP_UNICODE_IGNORE = { - LITERAL: LITERAL_UNI_IGNORE, - NOT_LITERAL: NOT_LITERAL_UNI_IGNORE, -} - -AT_MULTILINE = { - AT_BEGINNING: AT_BEGINNING_LINE, - AT_END: AT_END_LINE -} - -AT_LOCALE = { - AT_BOUNDARY: AT_LOC_BOUNDARY, - AT_NON_BOUNDARY: AT_LOC_NON_BOUNDARY -} - -AT_UNICODE = { - AT_BOUNDARY: AT_UNI_BOUNDARY, - AT_NON_BOUNDARY: AT_UNI_NON_BOUNDARY -} - -CH_LOCALE = { - CATEGORY_DIGIT: CATEGORY_DIGIT, - CATEGORY_NOT_DIGIT: CATEGORY_NOT_DIGIT, - CATEGORY_SPACE: CATEGORY_SPACE, - CATEGORY_NOT_SPACE: CATEGORY_NOT_SPACE, - CATEGORY_WORD: CATEGORY_LOC_WORD, - CATEGORY_NOT_WORD: CATEGORY_LOC_NOT_WORD, - CATEGORY_LINEBREAK: CATEGORY_LINEBREAK, - CATEGORY_NOT_LINEBREAK: CATEGORY_NOT_LINEBREAK -} - -CH_UNICODE = { - CATEGORY_DIGIT: CATEGORY_UNI_DIGIT, - CATEGORY_NOT_DIGIT: CATEGORY_UNI_NOT_DIGIT, - CATEGORY_SPACE: CATEGORY_UNI_SPACE, - CATEGORY_NOT_SPACE: CATEGORY_UNI_NOT_SPACE, - CATEGORY_WORD: CATEGORY_UNI_WORD, - CATEGORY_NOT_WORD: CATEGORY_UNI_NOT_WORD, - CATEGORY_LINEBREAK: CATEGORY_UNI_LINEBREAK, - CATEGORY_NOT_LINEBREAK: CATEGORY_UNI_NOT_LINEBREAK -} - -# flags -SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) -SRE_FLAG_IGNORECASE = 2 # case insensitive -SRE_FLAG_LOCALE = 4 # honour system locale -SRE_FLAG_MULTILINE = 8 # treat target as multiline string -SRE_FLAG_DOTALL = 16 # treat target as a single string -SRE_FLAG_UNICODE = 32 # use unicode "locale" -SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments -SRE_FLAG_DEBUG = 128 # debugging -SRE_FLAG_ASCII = 256 # use ascii "locale" - -# flags for INFO primitive -SRE_INFO_PREFIX = 1 # has prefix -SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix) -SRE_INFO_CHARSET = 4 # pattern starts with character from given set - -if __name__ == "__main__": - def dump(f, d, prefix): - items = sorted(d) - for item in items: - f.write("#define %s_%s %d\n" % (prefix, item, item)) - with open("sre_constants.h", "w") as f: - f.write("""\ -/* - * Secret Labs' Regular Expression Engine - * - * regular expression matching engine - * - * NOTE: This file is generated by sre_constants.py. If you need - * to change anything in here, edit sre_constants.py and run it. - * - * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. - * - * See the _sre.c file for information on usage and redistribution. - */ - -""") - - f.write("#define SRE_MAGIC %d\n" % MAGIC) - - dump(f, OPCODES, "SRE_OP") - dump(f, ATCODES, "SRE") - dump(f, CHCODES, "SRE") - - f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) - f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) - f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) - f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE) - f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) - f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) - f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) - f.write("#define SRE_FLAG_DEBUG %d\n" % SRE_FLAG_DEBUG) - f.write("#define SRE_FLAG_ASCII %d\n" % SRE_FLAG_ASCII) - - f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) - f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) - f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) - - print("done") diff --git a/experiment/simulation/backend/venv/lib/python3.7/sre_parse.py b/experiment/simulation/backend/venv/lib/python3.7/sre_parse.py deleted file mode 100644 index cb2c4c3..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/sre_parse.py +++ /dev/null @@ -1,1040 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# convert re-style regular expression to sre pattern -# -# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. -# -# See the sre.py file for information on usage and redistribution. -# - -"""Internal support module for sre""" - -# XXX: show string offset and offending character for all errors - -from sre_constants import * - -SPECIAL_CHARS = ".\\[{()*+?^$|" -REPEAT_CHARS = "*+?{" - -DIGITS = frozenset("0123456789") - -OCTDIGITS = frozenset("01234567") -HEXDIGITS = frozenset("0123456789abcdefABCDEF") -ASCIILETTERS = frozenset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -WHITESPACE = frozenset(" \t\n\r\v\f") - -_REPEATCODES = frozenset({MIN_REPEAT, MAX_REPEAT}) -_UNITCODES = frozenset({ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY}) - -ESCAPES = { - r"\a": (LITERAL, ord("\a")), - r"\b": (LITERAL, ord("\b")), - r"\f": (LITERAL, ord("\f")), - r"\n": (LITERAL, ord("\n")), - r"\r": (LITERAL, ord("\r")), - r"\t": (LITERAL, ord("\t")), - r"\v": (LITERAL, ord("\v")), - r"\\": (LITERAL, ord("\\")) -} - -CATEGORIES = { - r"\A": (AT, AT_BEGINNING_STRING), # start of string - r"\b": (AT, AT_BOUNDARY), - r"\B": (AT, AT_NON_BOUNDARY), - r"\d": (IN, [(CATEGORY, CATEGORY_DIGIT)]), - r"\D": (IN, [(CATEGORY, CATEGORY_NOT_DIGIT)]), - r"\s": (IN, [(CATEGORY, CATEGORY_SPACE)]), - r"\S": (IN, [(CATEGORY, CATEGORY_NOT_SPACE)]), - r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]), - r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]), - r"\Z": (AT, AT_END_STRING), # end of string -} - -FLAGS = { - # standard flags - "i": SRE_FLAG_IGNORECASE, - "L": SRE_FLAG_LOCALE, - "m": SRE_FLAG_MULTILINE, - "s": SRE_FLAG_DOTALL, - "x": SRE_FLAG_VERBOSE, - # extensions - "a": SRE_FLAG_ASCII, - "t": SRE_FLAG_TEMPLATE, - "u": SRE_FLAG_UNICODE, -} - -TYPE_FLAGS = SRE_FLAG_ASCII | SRE_FLAG_LOCALE | SRE_FLAG_UNICODE -GLOBAL_FLAGS = SRE_FLAG_DEBUG | SRE_FLAG_TEMPLATE - -class Verbose(Exception): - pass - -class Pattern: - # master pattern object. keeps track of global attributes - def __init__(self): - self.flags = 0 - self.groupdict = {} - self.groupwidths = [None] # group 0 - self.lookbehindgroups = None - @property - def groups(self): - return len(self.groupwidths) - def opengroup(self, name=None): - gid = self.groups - self.groupwidths.append(None) - if self.groups > MAXGROUPS: - raise error("too many groups") - if name is not None: - ogid = self.groupdict.get(name, None) - if ogid is not None: - raise error("redefinition of group name %r as group %d; " - "was group %d" % (name, gid, ogid)) - self.groupdict[name] = gid - return gid - def closegroup(self, gid, p): - self.groupwidths[gid] = p.getwidth() - def checkgroup(self, gid): - return gid < self.groups and self.groupwidths[gid] is not None - - def checklookbehindgroup(self, gid, source): - if self.lookbehindgroups is not None: - if not self.checkgroup(gid): - raise source.error('cannot refer to an open group') - if gid >= self.lookbehindgroups: - raise source.error('cannot refer to group defined in the same ' - 'lookbehind subpattern') - -class SubPattern: - # a subpattern, in intermediate form - def __init__(self, pattern, data=None): - self.pattern = pattern - if data is None: - data = [] - self.data = data - self.width = None - - def dump(self, level=0): - nl = True - seqtypes = (tuple, list) - for op, av in self.data: - print(level*" " + str(op), end='') - if op is IN: - # member sublanguage - print() - for op, a in av: - print((level+1)*" " + str(op), a) - elif op is BRANCH: - print() - for i, a in enumerate(av[1]): - if i: - print(level*" " + "OR") - a.dump(level+1) - elif op is GROUPREF_EXISTS: - condgroup, item_yes, item_no = av - print('', condgroup) - item_yes.dump(level+1) - if item_no: - print(level*" " + "ELSE") - item_no.dump(level+1) - elif isinstance(av, seqtypes): - nl = False - for a in av: - if isinstance(a, SubPattern): - if not nl: - print() - a.dump(level+1) - nl = True - else: - if not nl: - print(' ', end='') - print(a, end='') - nl = False - if not nl: - print() - else: - print('', av) - def __repr__(self): - return repr(self.data) - def __len__(self): - return len(self.data) - def __delitem__(self, index): - del self.data[index] - def __getitem__(self, index): - if isinstance(index, slice): - return SubPattern(self.pattern, self.data[index]) - return self.data[index] - def __setitem__(self, index, code): - self.data[index] = code - def insert(self, index, code): - self.data.insert(index, code) - def append(self, code): - self.data.append(code) - def getwidth(self): - # determine the width (min, max) for this subpattern - if self.width is not None: - return self.width - lo = hi = 0 - for op, av in self.data: - if op is BRANCH: - i = MAXREPEAT - 1 - j = 0 - for av in av[1]: - l, h = av.getwidth() - i = min(i, l) - j = max(j, h) - lo = lo + i - hi = hi + j - elif op is CALL: - i, j = av.getwidth() - lo = lo + i - hi = hi + j - elif op is SUBPATTERN: - i, j = av[-1].getwidth() - lo = lo + i - hi = hi + j - elif op in _REPEATCODES: - i, j = av[2].getwidth() - lo = lo + i * av[0] - hi = hi + j * av[1] - elif op in _UNITCODES: - lo = lo + 1 - hi = hi + 1 - elif op is GROUPREF: - i, j = self.pattern.groupwidths[av] - lo = lo + i - hi = hi + j - elif op is GROUPREF_EXISTS: - i, j = av[1].getwidth() - if av[2] is not None: - l, h = av[2].getwidth() - i = min(i, l) - j = max(j, h) - else: - i = 0 - lo = lo + i - hi = hi + j - elif op is SUCCESS: - break - self.width = min(lo, MAXREPEAT - 1), min(hi, MAXREPEAT) - return self.width - -class Tokenizer: - def __init__(self, string): - self.istext = isinstance(string, str) - self.string = string - if not self.istext: - string = str(string, 'latin1') - self.decoded_string = string - self.index = 0 - self.next = None - self.__next() - def __next(self): - index = self.index - try: - char = self.decoded_string[index] - except IndexError: - self.next = None - return - if char == "\\": - index += 1 - try: - char += self.decoded_string[index] - except IndexError: - raise error("bad escape (end of pattern)", - self.string, len(self.string) - 1) from None - self.index = index + 1 - self.next = char - def match(self, char): - if char == self.next: - self.__next() - return True - return False - def get(self): - this = self.next - self.__next() - return this - def getwhile(self, n, charset): - result = '' - for _ in range(n): - c = self.next - if c not in charset: - break - result += c - self.__next() - return result - def getuntil(self, terminator): - result = '' - while True: - c = self.next - self.__next() - if c is None: - if not result: - raise self.error("missing group name") - raise self.error("missing %s, unterminated name" % terminator, - len(result)) - if c == terminator: - if not result: - raise self.error("missing group name", 1) - break - result += c - return result - @property - def pos(self): - return self.index - len(self.next or '') - def tell(self): - return self.index - len(self.next or '') - def seek(self, index): - self.index = index - self.__next() - - def error(self, msg, offset=0): - return error(msg, self.string, self.tell() - offset) - -def _class_escape(source, escape): - # handle escape code inside character class - code = ESCAPES.get(escape) - if code: - return code - code = CATEGORIES.get(escape) - if code and code[0] is IN: - return code - try: - c = escape[1:2] - if c == "x": - # hexadecimal escape (exactly two digits) - escape += source.getwhile(2, HEXDIGITS) - if len(escape) != 4: - raise source.error("incomplete escape %s" % escape, len(escape)) - return LITERAL, int(escape[2:], 16) - elif c == "u" and source.istext: - # unicode escape (exactly four digits) - escape += source.getwhile(4, HEXDIGITS) - if len(escape) != 6: - raise source.error("incomplete escape %s" % escape, len(escape)) - return LITERAL, int(escape[2:], 16) - elif c == "U" and source.istext: - # unicode escape (exactly eight digits) - escape += source.getwhile(8, HEXDIGITS) - if len(escape) != 10: - raise source.error("incomplete escape %s" % escape, len(escape)) - c = int(escape[2:], 16) - chr(c) # raise ValueError for invalid code - return LITERAL, c - elif c in OCTDIGITS: - # octal escape (up to three digits) - escape += source.getwhile(2, OCTDIGITS) - c = int(escape[1:], 8) - if c > 0o377: - raise source.error('octal escape value %s outside of ' - 'range 0-0o377' % escape, len(escape)) - return LITERAL, c - elif c in DIGITS: - raise ValueError - if len(escape) == 2: - if c in ASCIILETTERS: - raise source.error('bad escape %s' % escape, len(escape)) - return LITERAL, ord(escape[1]) - except ValueError: - pass - raise source.error("bad escape %s" % escape, len(escape)) - -def _escape(source, escape, state): - # handle escape code in expression - code = CATEGORIES.get(escape) - if code: - return code - code = ESCAPES.get(escape) - if code: - return code - try: - c = escape[1:2] - if c == "x": - # hexadecimal escape - escape += source.getwhile(2, HEXDIGITS) - if len(escape) != 4: - raise source.error("incomplete escape %s" % escape, len(escape)) - return LITERAL, int(escape[2:], 16) - elif c == "u" and source.istext: - # unicode escape (exactly four digits) - escape += source.getwhile(4, HEXDIGITS) - if len(escape) != 6: - raise source.error("incomplete escape %s" % escape, len(escape)) - return LITERAL, int(escape[2:], 16) - elif c == "U" and source.istext: - # unicode escape (exactly eight digits) - escape += source.getwhile(8, HEXDIGITS) - if len(escape) != 10: - raise source.error("incomplete escape %s" % escape, len(escape)) - c = int(escape[2:], 16) - chr(c) # raise ValueError for invalid code - return LITERAL, c - elif c == "0": - # octal escape - escape += source.getwhile(2, OCTDIGITS) - return LITERAL, int(escape[1:], 8) - elif c in DIGITS: - # octal escape *or* decimal group reference (sigh) - if source.next in DIGITS: - escape += source.get() - if (escape[1] in OCTDIGITS and escape[2] in OCTDIGITS and - source.next in OCTDIGITS): - # got three octal digits; this is an octal escape - escape += source.get() - c = int(escape[1:], 8) - if c > 0o377: - raise source.error('octal escape value %s outside of ' - 'range 0-0o377' % escape, - len(escape)) - return LITERAL, c - # not an octal escape, so this is a group reference - group = int(escape[1:]) - if group < state.groups: - if not state.checkgroup(group): - raise source.error("cannot refer to an open group", - len(escape)) - state.checklookbehindgroup(group, source) - return GROUPREF, group - raise source.error("invalid group reference %d" % group, len(escape) - 1) - if len(escape) == 2: - if c in ASCIILETTERS: - raise source.error("bad escape %s" % escape, len(escape)) - return LITERAL, ord(escape[1]) - except ValueError: - pass - raise source.error("bad escape %s" % escape, len(escape)) - -def _uniq(items): - return list(dict.fromkeys(items)) - -def _parse_sub(source, state, verbose, nested): - # parse an alternation: a|b|c - - items = [] - itemsappend = items.append - sourcematch = source.match - start = source.tell() - while True: - itemsappend(_parse(source, state, verbose, nested + 1, - not nested and not items)) - if not sourcematch("|"): - break - - if len(items) == 1: - return items[0] - - subpattern = SubPattern(state) - - # check if all items share a common prefix - while True: - prefix = None - for item in items: - if not item: - break - if prefix is None: - prefix = item[0] - elif item[0] != prefix: - break - else: - # all subitems start with a common "prefix". - # move it out of the branch - for item in items: - del item[0] - subpattern.append(prefix) - continue # check next one - break - - # check if the branch can be replaced by a character set - set = [] - for item in items: - if len(item) != 1: - break - op, av = item[0] - if op is LITERAL: - set.append((op, av)) - elif op is IN and av[0][0] is not NEGATE: - set.extend(av) - else: - break - else: - # we can store this as a character set instead of a - # branch (the compiler may optimize this even more) - subpattern.append((IN, _uniq(set))) - return subpattern - - subpattern.append((BRANCH, (None, items))) - return subpattern - -def _parse(source, state, verbose, nested, first=False): - # parse a simple pattern - subpattern = SubPattern(state) - - # precompute constants into local variables - subpatternappend = subpattern.append - sourceget = source.get - sourcematch = source.match - _len = len - _ord = ord - - while True: - - this = source.next - if this is None: - break # end of pattern - if this in "|)": - break # end of subpattern - sourceget() - - if verbose: - # skip whitespace and comments - if this in WHITESPACE: - continue - if this == "#": - while True: - this = sourceget() - if this is None or this == "\n": - break - continue - - if this[0] == "\\": - code = _escape(source, this, state) - subpatternappend(code) - - elif this not in SPECIAL_CHARS: - subpatternappend((LITERAL, _ord(this))) - - elif this == "[": - here = source.tell() - 1 - # character set - set = [] - setappend = set.append -## if sourcematch(":"): -## pass # handle character classes - if source.next == '[': - import warnings - warnings.warn( - 'Possible nested set at position %d' % source.tell(), - FutureWarning, stacklevel=nested + 6 - ) - negate = sourcematch("^") - # check remaining characters - while True: - this = sourceget() - if this is None: - raise source.error("unterminated character set", - source.tell() - here) - if this == "]" and set: - break - elif this[0] == "\\": - code1 = _class_escape(source, this) - else: - if set and this in '-&~|' and source.next == this: - import warnings - warnings.warn( - 'Possible set %s at position %d' % ( - 'difference' if this == '-' else - 'intersection' if this == '&' else - 'symmetric difference' if this == '~' else - 'union', - source.tell() - 1), - FutureWarning, stacklevel=nested + 6 - ) - code1 = LITERAL, _ord(this) - if sourcematch("-"): - # potential range - that = sourceget() - if that is None: - raise source.error("unterminated character set", - source.tell() - here) - if that == "]": - if code1[0] is IN: - code1 = code1[1][0] - setappend(code1) - setappend((LITERAL, _ord("-"))) - break - if that[0] == "\\": - code2 = _class_escape(source, that) - else: - if that == '-': - import warnings - warnings.warn( - 'Possible set difference at position %d' % ( - source.tell() - 2), - FutureWarning, stacklevel=nested + 6 - ) - code2 = LITERAL, _ord(that) - if code1[0] != LITERAL or code2[0] != LITERAL: - msg = "bad character range %s-%s" % (this, that) - raise source.error(msg, len(this) + 1 + len(that)) - lo = code1[1] - hi = code2[1] - if hi < lo: - msg = "bad character range %s-%s" % (this, that) - raise source.error(msg, len(this) + 1 + len(that)) - setappend((RANGE, (lo, hi))) - else: - if code1[0] is IN: - code1 = code1[1][0] - setappend(code1) - - set = _uniq(set) - # XXX: should move set optimization to compiler! - if _len(set) == 1 and set[0][0] is LITERAL: - # optimization - if negate: - subpatternappend((NOT_LITERAL, set[0][1])) - else: - subpatternappend(set[0]) - else: - if negate: - set.insert(0, (NEGATE, None)) - # charmap optimization can't be added here because - # global flags still are not known - subpatternappend((IN, set)) - - elif this in REPEAT_CHARS: - # repeat previous item - here = source.tell() - if this == "?": - min, max = 0, 1 - elif this == "*": - min, max = 0, MAXREPEAT - - elif this == "+": - min, max = 1, MAXREPEAT - elif this == "{": - if source.next == "}": - subpatternappend((LITERAL, _ord(this))) - continue - - min, max = 0, MAXREPEAT - lo = hi = "" - while source.next in DIGITS: - lo += sourceget() - if sourcematch(","): - while source.next in DIGITS: - hi += sourceget() - else: - hi = lo - if not sourcematch("}"): - subpatternappend((LITERAL, _ord(this))) - source.seek(here) - continue - - if lo: - min = int(lo) - if min >= MAXREPEAT: - raise OverflowError("the repetition number is too large") - if hi: - max = int(hi) - if max >= MAXREPEAT: - raise OverflowError("the repetition number is too large") - if max < min: - raise source.error("min repeat greater than max repeat", - source.tell() - here) - else: - raise AssertionError("unsupported quantifier %r" % (char,)) - # figure out which item to repeat - if subpattern: - item = subpattern[-1:] - else: - item = None - if not item or item[0][0] is AT: - raise source.error("nothing to repeat", - source.tell() - here + len(this)) - if item[0][0] in _REPEATCODES: - raise source.error("multiple repeat", - source.tell() - here + len(this)) - if item[0][0] is SUBPATTERN: - group, add_flags, del_flags, p = item[0][1] - if group is None and not add_flags and not del_flags: - item = p - if sourcematch("?"): - subpattern[-1] = (MIN_REPEAT, (min, max, item)) - else: - subpattern[-1] = (MAX_REPEAT, (min, max, item)) - - elif this == ".": - subpatternappend((ANY, None)) - - elif this == "(": - start = source.tell() - 1 - group = True - name = None - add_flags = 0 - del_flags = 0 - if sourcematch("?"): - # options - char = sourceget() - if char is None: - raise source.error("unexpected end of pattern") - if char == "P": - # python extensions - if sourcematch("<"): - # named group: skip forward to end of name - name = source.getuntil(">") - if not name.isidentifier(): - msg = "bad character in group name %r" % name - raise source.error(msg, len(name) + 1) - elif sourcematch("="): - # named backreference - name = source.getuntil(")") - if not name.isidentifier(): - msg = "bad character in group name %r" % name - raise source.error(msg, len(name) + 1) - gid = state.groupdict.get(name) - if gid is None: - msg = "unknown group name %r" % name - raise source.error(msg, len(name) + 1) - if not state.checkgroup(gid): - raise source.error("cannot refer to an open group", - len(name) + 1) - state.checklookbehindgroup(gid, source) - subpatternappend((GROUPREF, gid)) - continue - - else: - char = sourceget() - if char is None: - raise source.error("unexpected end of pattern") - raise source.error("unknown extension ?P" + char, - len(char) + 2) - elif char == ":": - # non-capturing group - group = None - elif char == "#": - # comment - while True: - if source.next is None: - raise source.error("missing ), unterminated comment", - source.tell() - start) - if sourceget() == ")": - break - continue - - elif char in "=!<": - # lookahead assertions - dir = 1 - if char == "<": - char = sourceget() - if char is None: - raise source.error("unexpected end of pattern") - if char not in "=!": - raise source.error("unknown extension ?<" + char, - len(char) + 2) - dir = -1 # lookbehind - lookbehindgroups = state.lookbehindgroups - if lookbehindgroups is None: - state.lookbehindgroups = state.groups - p = _parse_sub(source, state, verbose, nested + 1) - if dir < 0: - if lookbehindgroups is None: - state.lookbehindgroups = None - if not sourcematch(")"): - raise source.error("missing ), unterminated subpattern", - source.tell() - start) - if char == "=": - subpatternappend((ASSERT, (dir, p))) - else: - subpatternappend((ASSERT_NOT, (dir, p))) - continue - - elif char == "(": - # conditional backreference group - condname = source.getuntil(")") - if condname.isidentifier(): - condgroup = state.groupdict.get(condname) - if condgroup is None: - msg = "unknown group name %r" % condname - raise source.error(msg, len(condname) + 1) - else: - try: - condgroup = int(condname) - if condgroup < 0: - raise ValueError - except ValueError: - msg = "bad character in group name %r" % condname - raise source.error(msg, len(condname) + 1) from None - if not condgroup: - raise source.error("bad group number", - len(condname) + 1) - if condgroup >= MAXGROUPS: - msg = "invalid group reference %d" % condgroup - raise source.error(msg, len(condname) + 1) - state.checklookbehindgroup(condgroup, source) - item_yes = _parse(source, state, verbose, nested + 1) - if source.match("|"): - item_no = _parse(source, state, verbose, nested + 1) - if source.next == "|": - raise source.error("conditional backref with more than two branches") - else: - item_no = None - if not source.match(")"): - raise source.error("missing ), unterminated subpattern", - source.tell() - start) - subpatternappend((GROUPREF_EXISTS, (condgroup, item_yes, item_no))) - continue - - elif char in FLAGS or char == "-": - # flags - flags = _parse_flags(source, state, char) - if flags is None: # global flags - if not first or subpattern: - import warnings - warnings.warn( - 'Flags not at the start of the expression %r%s' % ( - source.string[:20], # truncate long regexes - ' (truncated)' if len(source.string) > 20 else '', - ), - DeprecationWarning, stacklevel=nested + 6 - ) - if (state.flags & SRE_FLAG_VERBOSE) and not verbose: - raise Verbose - continue - - add_flags, del_flags = flags - group = None - else: - raise source.error("unknown extension ?" + char, - len(char) + 1) - - # parse group contents - if group is not None: - try: - group = state.opengroup(name) - except error as err: - raise source.error(err.msg, len(name) + 1) from None - sub_verbose = ((verbose or (add_flags & SRE_FLAG_VERBOSE)) and - not (del_flags & SRE_FLAG_VERBOSE)) - p = _parse_sub(source, state, sub_verbose, nested + 1) - if not source.match(")"): - raise source.error("missing ), unterminated subpattern", - source.tell() - start) - if group is not None: - state.closegroup(group, p) - subpatternappend((SUBPATTERN, (group, add_flags, del_flags, p))) - - elif this == "^": - subpatternappend((AT, AT_BEGINNING)) - - elif this == "$": - subpatternappend((AT, AT_END)) - - else: - raise AssertionError("unsupported special character %r" % (char,)) - - # unpack non-capturing groups - for i in range(len(subpattern))[::-1]: - op, av = subpattern[i] - if op is SUBPATTERN: - group, add_flags, del_flags, p = av - if group is None and not add_flags and not del_flags: - subpattern[i: i+1] = p - - return subpattern - -def _parse_flags(source, state, char): - sourceget = source.get - add_flags = 0 - del_flags = 0 - if char != "-": - while True: - flag = FLAGS[char] - if source.istext: - if char == 'L': - msg = "bad inline flags: cannot use 'L' flag with a str pattern" - raise source.error(msg) - else: - if char == 'u': - msg = "bad inline flags: cannot use 'u' flag with a bytes pattern" - raise source.error(msg) - add_flags |= flag - if (flag & TYPE_FLAGS) and (add_flags & TYPE_FLAGS) != flag: - msg = "bad inline flags: flags 'a', 'u' and 'L' are incompatible" - raise source.error(msg) - char = sourceget() - if char is None: - raise source.error("missing -, : or )") - if char in ")-:": - break - if char not in FLAGS: - msg = "unknown flag" if char.isalpha() else "missing -, : or )" - raise source.error(msg, len(char)) - if char == ")": - state.flags |= add_flags - return None - if add_flags & GLOBAL_FLAGS: - raise source.error("bad inline flags: cannot turn on global flag", 1) - if char == "-": - char = sourceget() - if char is None: - raise source.error("missing flag") - if char not in FLAGS: - msg = "unknown flag" if char.isalpha() else "missing flag" - raise source.error(msg, len(char)) - while True: - flag = FLAGS[char] - if flag & TYPE_FLAGS: - msg = "bad inline flags: cannot turn off flags 'a', 'u' and 'L'" - raise source.error(msg) - del_flags |= flag - char = sourceget() - if char is None: - raise source.error("missing :") - if char == ":": - break - if char not in FLAGS: - msg = "unknown flag" if char.isalpha() else "missing :" - raise source.error(msg, len(char)) - assert char == ":" - if del_flags & GLOBAL_FLAGS: - raise source.error("bad inline flags: cannot turn off global flag", 1) - if add_flags & del_flags: - raise source.error("bad inline flags: flag turned on and off", 1) - return add_flags, del_flags - -def fix_flags(src, flags): - # Check and fix flags according to the type of pattern (str or bytes) - if isinstance(src, str): - if flags & SRE_FLAG_LOCALE: - raise ValueError("cannot use LOCALE flag with a str pattern") - if not flags & SRE_FLAG_ASCII: - flags |= SRE_FLAG_UNICODE - elif flags & SRE_FLAG_UNICODE: - raise ValueError("ASCII and UNICODE flags are incompatible") - else: - if flags & SRE_FLAG_UNICODE: - raise ValueError("cannot use UNICODE flag with a bytes pattern") - if flags & SRE_FLAG_LOCALE and flags & SRE_FLAG_ASCII: - raise ValueError("ASCII and LOCALE flags are incompatible") - return flags - -def parse(str, flags=0, pattern=None): - # parse 're' pattern into list of (opcode, argument) tuples - - source = Tokenizer(str) - - if pattern is None: - pattern = Pattern() - pattern.flags = flags - pattern.str = str - - try: - p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0) - except Verbose: - # the VERBOSE flag was switched on inside the pattern. to be - # on the safe side, we'll parse the whole thing again... - pattern = Pattern() - pattern.flags = flags | SRE_FLAG_VERBOSE - pattern.str = str - source.seek(0) - p = _parse_sub(source, pattern, True, 0) - - p.pattern.flags = fix_flags(str, p.pattern.flags) - - if source.next is not None: - assert source.next == ")" - raise source.error("unbalanced parenthesis") - - if flags & SRE_FLAG_DEBUG: - p.dump() - - return p - -def parse_template(source, pattern): - # parse 're' replacement string into list of literals and - # group references - s = Tokenizer(source) - sget = s.get - groups = [] - literals = [] - literal = [] - lappend = literal.append - def addgroup(index, pos): - if index > pattern.groups: - raise s.error("invalid group reference %d" % index, pos) - if literal: - literals.append(''.join(literal)) - del literal[:] - groups.append((len(literals), index)) - literals.append(None) - groupindex = pattern.groupindex - while True: - this = sget() - if this is None: - break # end of replacement string - if this[0] == "\\": - # group - c = this[1] - if c == "g": - name = "" - if not s.match("<"): - raise s.error("missing <") - name = s.getuntil(">") - if name.isidentifier(): - try: - index = groupindex[name] - except KeyError: - raise IndexError("unknown group name %r" % name) - else: - try: - index = int(name) - if index < 0: - raise ValueError - except ValueError: - raise s.error("bad character in group name %r" % name, - len(name) + 1) from None - if index >= MAXGROUPS: - raise s.error("invalid group reference %d" % index, - len(name) + 1) - addgroup(index, len(name) + 1) - elif c == "0": - if s.next in OCTDIGITS: - this += sget() - if s.next in OCTDIGITS: - this += sget() - lappend(chr(int(this[1:], 8) & 0xff)) - elif c in DIGITS: - isoctal = False - if s.next in DIGITS: - this += sget() - if (c in OCTDIGITS and this[2] in OCTDIGITS and - s.next in OCTDIGITS): - this += sget() - isoctal = True - c = int(this[1:], 8) - if c > 0o377: - raise s.error('octal escape value %s outside of ' - 'range 0-0o377' % this, len(this)) - lappend(chr(c)) - if not isoctal: - addgroup(int(this[1:]), len(this) - 1) - else: - try: - this = chr(ESCAPES[this][1]) - except KeyError: - if c in ASCIILETTERS: - raise s.error('bad escape %s' % this, len(this)) - lappend(this) - else: - lappend(this) - if literal: - literals.append(''.join(literal)) - if not isinstance(source, str): - # The tokenizer implicitly decodes bytes objects as latin-1, we must - # therefore re-encode the final representation. - literals = [None if s is None else s.encode('latin-1') for s in literals] - return groups, literals - -def expand_template(template, match): - g = match.group - empty = match.string[:0] - groups, literals = template - literals = literals[:] - try: - for index, group in groups: - literals[index] = g(group) or empty - except IndexError: - raise error("invalid group reference %d" % index) - return empty.join(literals) diff --git a/experiment/simulation/backend/venv/lib/python3.7/stat.py b/experiment/simulation/backend/venv/lib/python3.7/stat.py deleted file mode 100644 index 165e057..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/stat.py +++ /dev/null @@ -1,194 +0,0 @@ -"""Constants/functions for interpreting results of os.stat() and os.lstat(). - -Suggested usage: from stat import * -""" - -# Indices for stat struct members in the tuple returned by os.stat() - -ST_MODE = 0 -ST_INO = 1 -ST_DEV = 2 -ST_NLINK = 3 -ST_UID = 4 -ST_GID = 5 -ST_SIZE = 6 -ST_ATIME = 7 -ST_MTIME = 8 -ST_CTIME = 9 - -# Extract bits from the mode - -def S_IMODE(mode): - """Return the portion of the file's mode that can be set by - os.chmod(). - """ - return mode & 0o7777 - -def S_IFMT(mode): - """Return the portion of the file's mode that describes the - file type. - """ - return mode & 0o170000 - -# Constants used as S_IFMT() for various file types -# (not all are implemented on all systems) - -S_IFDIR = 0o040000 # directory -S_IFCHR = 0o020000 # character device -S_IFBLK = 0o060000 # block device -S_IFREG = 0o100000 # regular file -S_IFIFO = 0o010000 # fifo (named pipe) -S_IFLNK = 0o120000 # symbolic link -S_IFSOCK = 0o140000 # socket file -# Fallbacks for uncommon platform-specific constants -S_IFDOOR = 0 -S_IFPORT = 0 -S_IFWHT = 0 - -# Functions to test for each file type - -def S_ISDIR(mode): - """Return True if mode is from a directory.""" - return S_IFMT(mode) == S_IFDIR - -def S_ISCHR(mode): - """Return True if mode is from a character special device file.""" - return S_IFMT(mode) == S_IFCHR - -def S_ISBLK(mode): - """Return True if mode is from a block special device file.""" - return S_IFMT(mode) == S_IFBLK - -def S_ISREG(mode): - """Return True if mode is from a regular file.""" - return S_IFMT(mode) == S_IFREG - -def S_ISFIFO(mode): - """Return True if mode is from a FIFO (named pipe).""" - return S_IFMT(mode) == S_IFIFO - -def S_ISLNK(mode): - """Return True if mode is from a symbolic link.""" - return S_IFMT(mode) == S_IFLNK - -def S_ISSOCK(mode): - """Return True if mode is from a socket.""" - return S_IFMT(mode) == S_IFSOCK - -def S_ISDOOR(mode): - """Return True if mode is from a door.""" - return False - -def S_ISPORT(mode): - """Return True if mode is from an event port.""" - return False - -def S_ISWHT(mode): - """Return True if mode is from a whiteout.""" - return False - -# Names for permission bits - -S_ISUID = 0o4000 # set UID bit -S_ISGID = 0o2000 # set GID bit -S_ENFMT = S_ISGID # file locking enforcement -S_ISVTX = 0o1000 # sticky bit -S_IREAD = 0o0400 # Unix V7 synonym for S_IRUSR -S_IWRITE = 0o0200 # Unix V7 synonym for S_IWUSR -S_IEXEC = 0o0100 # Unix V7 synonym for S_IXUSR -S_IRWXU = 0o0700 # mask for owner permissions -S_IRUSR = 0o0400 # read by owner -S_IWUSR = 0o0200 # write by owner -S_IXUSR = 0o0100 # execute by owner -S_IRWXG = 0o0070 # mask for group permissions -S_IRGRP = 0o0040 # read by group -S_IWGRP = 0o0020 # write by group -S_IXGRP = 0o0010 # execute by group -S_IRWXO = 0o0007 # mask for others (not in group) permissions -S_IROTH = 0o0004 # read by others -S_IWOTH = 0o0002 # write by others -S_IXOTH = 0o0001 # execute by others - -# Names for file flags - -UF_NODUMP = 0x00000001 # do not dump file -UF_IMMUTABLE = 0x00000002 # file may not be changed -UF_APPEND = 0x00000004 # file may only be appended to -UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack -UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted -UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed -UF_HIDDEN = 0x00008000 # OS X: file should not be displayed -SF_ARCHIVED = 0x00010000 # file may be archived -SF_IMMUTABLE = 0x00020000 # file may not be changed -SF_APPEND = 0x00040000 # file may only be appended to -SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted -SF_SNAPSHOT = 0x00200000 # file is a snapshot file - - -_filemode_table = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), - - ((S_IRUSR, "r"),), - ((S_IWUSR, "w"),), - ((S_IXUSR|S_ISUID, "s"), - (S_ISUID, "S"), - (S_IXUSR, "x")), - - ((S_IRGRP, "r"),), - ((S_IWGRP, "w"),), - ((S_IXGRP|S_ISGID, "s"), - (S_ISGID, "S"), - (S_IXGRP, "x")), - - ((S_IROTH, "r"),), - ((S_IWOTH, "w"),), - ((S_IXOTH|S_ISVTX, "t"), - (S_ISVTX, "T"), - (S_IXOTH, "x")) -) - -def filemode(mode): - """Convert a file's mode to a string of the form '-rwxrwxrwx'.""" - perm = [] - for table in _filemode_table: - for bit, char in table: - if mode & bit == bit: - perm.append(char) - break - else: - perm.append("-") - return "".join(perm) - - -# Windows FILE_ATTRIBUTE constants for interpreting os.stat()'s -# "st_file_attributes" member - -FILE_ATTRIBUTE_ARCHIVE = 32 -FILE_ATTRIBUTE_COMPRESSED = 2048 -FILE_ATTRIBUTE_DEVICE = 64 -FILE_ATTRIBUTE_DIRECTORY = 16 -FILE_ATTRIBUTE_ENCRYPTED = 16384 -FILE_ATTRIBUTE_HIDDEN = 2 -FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 -FILE_ATTRIBUTE_NORMAL = 128 -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 -FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072 -FILE_ATTRIBUTE_OFFLINE = 4096 -FILE_ATTRIBUTE_READONLY = 1 -FILE_ATTRIBUTE_REPARSE_POINT = 1024 -FILE_ATTRIBUTE_SPARSE_FILE = 512 -FILE_ATTRIBUTE_SYSTEM = 4 -FILE_ATTRIBUTE_TEMPORARY = 256 -FILE_ATTRIBUTE_VIRTUAL = 65536 - - -# If available, use C implementation -try: - from _stat import * -except ImportError: - pass diff --git a/experiment/simulation/backend/venv/lib/python3.7/struct.py b/experiment/simulation/backend/venv/lib/python3.7/struct.py deleted file mode 100644 index d6bba58..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/struct.py +++ /dev/null @@ -1,15 +0,0 @@ -__all__ = [ - # Functions - 'calcsize', 'pack', 'pack_into', 'unpack', 'unpack_from', - 'iter_unpack', - - # Classes - 'Struct', - - # Exceptions - 'error' - ] - -from _struct import * -from _struct import _clearcache -from _struct import __doc__ diff --git a/experiment/simulation/backend/venv/lib/python3.7/tarfile.py b/experiment/simulation/backend/venv/lib/python3.7/tarfile.py deleted file mode 100755 index 3b596cb..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/tarfile.py +++ /dev/null @@ -1,2537 +0,0 @@ -#!/usr/bin/env python3 -#------------------------------------------------------------------- -# tarfile.py -#------------------------------------------------------------------- -# Copyright (C) 2002 Lars Gustaebel -# All rights reserved. -# -# 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. -# -"""Read from and write to tar format archives. -""" - -version = "0.9.0" -__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" -__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." - -#--------- -# Imports -#--------- -from builtins import open as bltn_open -import sys -import os -import io -import shutil -import stat -import time -import struct -import copy -import re - -try: - import pwd -except ImportError: - pwd = None -try: - import grp -except ImportError: - grp = None - -# os.symlink on Windows prior to 6.0 raises NotImplementedError -symlink_exception = (AttributeError, NotImplementedError) -try: - # OSError (winerror=1314) will be raised if the caller does not hold the - # SeCreateSymbolicLinkPrivilege privilege - symlink_exception += (OSError,) -except NameError: - pass - -# from tarfile import * -__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError", - "CompressionError", "StreamError", "ExtractError", "HeaderError", - "ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT", - "DEFAULT_FORMAT", "open"] - -#--------------------------------------------------------- -# tar constants -#--------------------------------------------------------- -NUL = b"\0" # the null character -BLOCKSIZE = 512 # length of processing blocks -RECORDSIZE = BLOCKSIZE * 20 # length of records -GNU_MAGIC = b"ustar \0" # magic gnu tar string -POSIX_MAGIC = b"ustar\x0000" # magic posix tar string - -LENGTH_NAME = 100 # maximum length of a filename -LENGTH_LINK = 100 # maximum length of a linkname -LENGTH_PREFIX = 155 # maximum length of the prefix field - -REGTYPE = b"0" # regular file -AREGTYPE = b"\0" # regular file -LNKTYPE = b"1" # link (inside tarfile) -SYMTYPE = b"2" # symbolic link -CHRTYPE = b"3" # character special device -BLKTYPE = b"4" # block special device -DIRTYPE = b"5" # directory -FIFOTYPE = b"6" # fifo special device -CONTTYPE = b"7" # contiguous file - -GNUTYPE_LONGNAME = b"L" # GNU tar longname -GNUTYPE_LONGLINK = b"K" # GNU tar longlink -GNUTYPE_SPARSE = b"S" # GNU tar sparse file - -XHDTYPE = b"x" # POSIX.1-2001 extended header -XGLTYPE = b"g" # POSIX.1-2001 global header -SOLARIS_XHDTYPE = b"X" # Solaris extended header - -USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format -GNU_FORMAT = 1 # GNU tar format -PAX_FORMAT = 2 # POSIX.1-2001 (pax) format -DEFAULT_FORMAT = GNU_FORMAT - -#--------------------------------------------------------- -# tarfile constants -#--------------------------------------------------------- -# File types that tarfile supports: -SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, - SYMTYPE, DIRTYPE, FIFOTYPE, - CONTTYPE, CHRTYPE, BLKTYPE, - GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# File types that will be treated as a regular file. -REGULAR_TYPES = (REGTYPE, AREGTYPE, - CONTTYPE, GNUTYPE_SPARSE) - -# File types that are part of the GNU tar format. -GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# Fields from a pax header that override a TarInfo attribute. -PAX_FIELDS = ("path", "linkpath", "size", "mtime", - "uid", "gid", "uname", "gname") - -# Fields from a pax header that are affected by hdrcharset. -PAX_NAME_FIELDS = {"path", "linkpath", "uname", "gname"} - -# Fields in a pax header that are numbers, all other fields -# are treated as strings. -PAX_NUMBER_FIELDS = { - "atime": float, - "ctime": float, - "mtime": float, - "uid": int, - "gid": int, - "size": int -} - -#--------------------------------------------------------- -# initialization -#--------------------------------------------------------- -if os.name == "nt": - ENCODING = "utf-8" -else: - ENCODING = sys.getfilesystemencoding() - -#--------------------------------------------------------- -# Some useful functions -#--------------------------------------------------------- - -def stn(s, length, encoding, errors): - """Convert a string to a null-terminated bytes object. - """ - s = s.encode(encoding, errors) - return s[:length] + (length - len(s)) * NUL - -def nts(s, encoding, errors): - """Convert a null-terminated bytes object to a string. - """ - p = s.find(b"\0") - if p != -1: - s = s[:p] - return s.decode(encoding, errors) - -def nti(s): - """Convert a number field to a python number. - """ - # There are two possible encodings for a number field, see - # itn() below. - if s[0] in (0o200, 0o377): - n = 0 - for i in range(len(s) - 1): - n <<= 8 - n += s[i + 1] - if s[0] == 0o377: - n = -(256 ** (len(s) - 1) - n) - else: - try: - s = nts(s, "ascii", "strict") - n = int(s.strip() or "0", 8) - except ValueError: - raise InvalidHeaderError("invalid header") - return n - -def itn(n, digits=8, format=DEFAULT_FORMAT): - """Convert a python number to a number field. - """ - # POSIX 1003.1-1988 requires numbers to be encoded as a string of - # octal digits followed by a null-byte, this allows values up to - # (8**(digits-1))-1. GNU tar allows storing numbers greater than - # that if necessary. A leading 0o200 or 0o377 byte indicate this - # particular encoding, the following digits-1 bytes are a big-endian - # base-256 representation. This allows values up to (256**(digits-1))-1. - # A 0o200 byte indicates a positive number, a 0o377 byte a negative - # number. - n = int(n) - if 0 <= n < 8 ** (digits - 1): - s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL - elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1): - if n >= 0: - s = bytearray([0o200]) - else: - s = bytearray([0o377]) - n = 256 ** digits + n - - for i in range(digits - 1): - s.insert(1, n & 0o377) - n >>= 8 - else: - raise ValueError("overflow in number field") - - return s - -def calc_chksums(buf): - """Calculate the checksum for a member's header by summing up all - characters except for the chksum field which is treated as if - it was filled with spaces. According to the GNU tar sources, - some tars (Sun and NeXT) calculate chksum with signed char, - which will be different if there are chars in the buffer with - the high bit set. So we calculate two checksums, unsigned and - signed. - """ - unsigned_chksum = 256 + sum(struct.unpack_from("148B8x356B", buf)) - signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf)) - return unsigned_chksum, signed_chksum - -def copyfileobj(src, dst, length=None, exception=OSError, bufsize=None): - """Copy length bytes from fileobj src to fileobj dst. - If length is None, copy the entire content. - """ - bufsize = bufsize or 16 * 1024 - if length == 0: - return - if length is None: - shutil.copyfileobj(src, dst, bufsize) - return - - blocks, remainder = divmod(length, bufsize) - for b in range(blocks): - buf = src.read(bufsize) - if len(buf) < bufsize: - raise exception("unexpected end of data") - dst.write(buf) - - if remainder != 0: - buf = src.read(remainder) - if len(buf) < remainder: - raise exception("unexpected end of data") - dst.write(buf) - return - -def filemode(mode): - """Deprecated in this location; use stat.filemode.""" - import warnings - warnings.warn("deprecated in favor of stat.filemode", - DeprecationWarning, 2) - return stat.filemode(mode) - -def _safe_print(s): - encoding = getattr(sys.stdout, 'encoding', None) - if encoding is not None: - s = s.encode(encoding, 'backslashreplace').decode(encoding) - print(s, end=' ') - - -class TarError(Exception): - """Base exception.""" - pass -class ExtractError(TarError): - """General exception for extract errors.""" - pass -class ReadError(TarError): - """Exception for unreadable tar archives.""" - pass -class CompressionError(TarError): - """Exception for unavailable compression methods.""" - pass -class StreamError(TarError): - """Exception for unsupported operations on stream-like TarFiles.""" - pass -class HeaderError(TarError): - """Base exception for header errors.""" - pass -class EmptyHeaderError(HeaderError): - """Exception for empty headers.""" - pass -class TruncatedHeaderError(HeaderError): - """Exception for truncated headers.""" - pass -class EOFHeaderError(HeaderError): - """Exception for end of file headers.""" - pass -class InvalidHeaderError(HeaderError): - """Exception for invalid headers.""" - pass -class SubsequentHeaderError(HeaderError): - """Exception for missing and invalid extended headers.""" - pass - -#--------------------------- -# internal stream interface -#--------------------------- -class _LowLevelFile: - """Low-level file object. Supports reading and writing. - It is used instead of a regular file object for streaming - access. - """ - - def __init__(self, name, mode): - mode = { - "r": os.O_RDONLY, - "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, - }[mode] - if hasattr(os, "O_BINARY"): - mode |= os.O_BINARY - self.fd = os.open(name, mode, 0o666) - - def close(self): - os.close(self.fd) - - def read(self, size): - return os.read(self.fd, size) - - def write(self, s): - os.write(self.fd, s) - -class _Stream: - """Class that serves as an adapter between TarFile and - a stream-like object. The stream-like object only - needs to have a read() or write() method and is accessed - blockwise. Use of gzip or bzip2 compression is possible. - A stream-like object could be for example: sys.stdin, - sys.stdout, a socket, a tape device etc. - - _Stream is intended to be used only internally. - """ - - def __init__(self, name, mode, comptype, fileobj, bufsize): - """Construct a _Stream object. - """ - self._extfileobj = True - if fileobj is None: - fileobj = _LowLevelFile(name, mode) - self._extfileobj = False - - if comptype == '*': - # Enable transparent compression detection for the - # stream interface - fileobj = _StreamProxy(fileobj) - comptype = fileobj.getcomptype() - - self.name = name or "" - self.mode = mode - self.comptype = comptype - self.fileobj = fileobj - self.bufsize = bufsize - self.buf = b"" - self.pos = 0 - self.closed = False - - try: - if comptype == "gz": - try: - import zlib - except ImportError: - raise CompressionError("zlib module is not available") - self.zlib = zlib - self.crc = zlib.crc32(b"") - if mode == "r": - self._init_read_gz() - self.exception = zlib.error - else: - self._init_write_gz() - - elif comptype == "bz2": - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - if mode == "r": - self.dbuf = b"" - self.cmp = bz2.BZ2Decompressor() - self.exception = OSError - else: - self.cmp = bz2.BZ2Compressor() - - elif comptype == "xz": - try: - import lzma - except ImportError: - raise CompressionError("lzma module is not available") - if mode == "r": - self.dbuf = b"" - self.cmp = lzma.LZMADecompressor() - self.exception = lzma.LZMAError - else: - self.cmp = lzma.LZMACompressor() - - elif comptype != "tar": - raise CompressionError("unknown compression type %r" % comptype) - - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - def __del__(self): - if hasattr(self, "closed") and not self.closed: - self.close() - - def _init_write_gz(self): - """Initialize for writing with gzip compression. - """ - self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, - -self.zlib.MAX_WBITS, - self.zlib.DEF_MEM_LEVEL, - 0) - timestamp = struct.pack(" self.bufsize: - self.fileobj.write(self.buf[:self.bufsize]) - self.buf = self.buf[self.bufsize:] - - def close(self): - """Close the _Stream object. No operation should be - done on it afterwards. - """ - if self.closed: - return - - self.closed = True - try: - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() - - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - self.fileobj.write(struct.pack("= 0: - blocks, remainder = divmod(pos - self.pos, self.bufsize) - for i in range(blocks): - self.read(self.bufsize) - self.read(remainder) - else: - raise StreamError("seeking backwards is not allowed") - return self.pos - - def read(self, size=None): - """Return the next size number of bytes from the stream. - If size is not defined, return all bytes of the stream - up to EOF. - """ - if size is None: - t = [] - while True: - buf = self._read(self.bufsize) - if not buf: - break - t.append(buf) - buf = b"".join(t) - else: - buf = self._read(size) - self.pos += len(buf) - return buf - - def _read(self, size): - """Return size bytes from the stream. - """ - if self.comptype == "tar": - return self.__read(size) - - c = len(self.dbuf) - t = [self.dbuf] - while c < size: - buf = self.__read(self.bufsize) - if not buf: - break - try: - buf = self.cmp.decompress(buf) - except self.exception: - raise ReadError("invalid compressed data") - t.append(buf) - c += len(buf) - t = b"".join(t) - self.dbuf = t[size:] - return t[:size] - - def __read(self, size): - """Return size bytes from stream. If internal buffer is empty, - read another block from the stream. - """ - c = len(self.buf) - t = [self.buf] - while c < size: - buf = self.fileobj.read(self.bufsize) - if not buf: - break - t.append(buf) - c += len(buf) - t = b"".join(t) - self.buf = t[size:] - return t[:size] -# class _Stream - -class _StreamProxy(object): - """Small proxy class that enables transparent compression - detection for the Stream interface (mode 'r|*'). - """ - - def __init__(self, fileobj): - self.fileobj = fileobj - self.buf = self.fileobj.read(BLOCKSIZE) - - def read(self, size): - self.read = self.fileobj.read - return self.buf - - def getcomptype(self): - if self.buf.startswith(b"\x1f\x8b\x08"): - return "gz" - elif self.buf[0:3] == b"BZh" and self.buf[4:10] == b"1AY&SY": - return "bz2" - elif self.buf.startswith((b"\x5d\x00\x00\x80", b"\xfd7zXZ")): - return "xz" - else: - return "tar" - - def close(self): - self.fileobj.close() -# class StreamProxy - -#------------------------ -# Extraction file object -#------------------------ -class _FileInFile(object): - """A thin wrapper around an existing file object that - provides a part of its data as an individual file - object. - """ - - def __init__(self, fileobj, offset, size, blockinfo=None): - self.fileobj = fileobj - self.offset = offset - self.size = size - self.position = 0 - self.name = getattr(fileobj, "name", None) - self.closed = False - - if blockinfo is None: - blockinfo = [(0, size)] - - # Construct a map with data and zero blocks. - self.map_index = 0 - self.map = [] - lastpos = 0 - realpos = self.offset - for offset, size in blockinfo: - if offset > lastpos: - self.map.append((False, lastpos, offset, None)) - self.map.append((True, offset, offset + size, realpos)) - realpos += size - lastpos = offset + size - if lastpos < self.size: - self.map.append((False, lastpos, self.size, None)) - - def flush(self): - pass - - def readable(self): - return True - - def writable(self): - return False - - def seekable(self): - return self.fileobj.seekable() - - def tell(self): - """Return the current file position. - """ - return self.position - - def seek(self, position, whence=io.SEEK_SET): - """Seek to a position in the file. - """ - if whence == io.SEEK_SET: - self.position = min(max(position, 0), self.size) - elif whence == io.SEEK_CUR: - if position < 0: - self.position = max(self.position + position, 0) - else: - self.position = min(self.position + position, self.size) - elif whence == io.SEEK_END: - self.position = max(min(self.size + position, self.size), 0) - else: - raise ValueError("Invalid argument") - return self.position - - def read(self, size=None): - """Read data from the file. - """ - if size is None: - size = self.size - self.position - else: - size = min(size, self.size - self.position) - - buf = b"" - while size > 0: - while True: - data, start, stop, offset = self.map[self.map_index] - if start <= self.position < stop: - break - else: - self.map_index += 1 - if self.map_index == len(self.map): - self.map_index = 0 - length = min(size, stop - self.position) - if data: - self.fileobj.seek(offset + (self.position - start)) - b = self.fileobj.read(length) - if len(b) != length: - raise ReadError("unexpected end of data") - buf += b - else: - buf += NUL * length - size -= length - self.position += length - return buf - - def readinto(self, b): - buf = self.read(len(b)) - b[:len(buf)] = buf - return len(buf) - - def close(self): - self.closed = True -#class _FileInFile - -class ExFileObject(io.BufferedReader): - - def __init__(self, tarfile, tarinfo): - fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data, - tarinfo.size, tarinfo.sparse) - super().__init__(fileobj) -#class ExFileObject - -#------------------ -# Exported Classes -#------------------ -class TarInfo(object): - """Informational class which holds the details about an - archive member given by a tar header block. - TarInfo objects are returned by TarFile.getmember(), - TarFile.getmembers() and TarFile.gettarinfo() and are - usually created internally. - """ - - __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", - "chksum", "type", "linkname", "uname", "gname", - "devmajor", "devminor", - "offset", "offset_data", "pax_headers", "sparse", - "tarfile", "_sparse_structs", "_link_target") - - def __init__(self, name=""): - """Construct a TarInfo object. name is the optional name - of the member. - """ - self.name = name # member name - self.mode = 0o644 # file permissions - self.uid = 0 # user id - self.gid = 0 # group id - self.size = 0 # file size - self.mtime = 0 # modification time - self.chksum = 0 # header checksum - self.type = REGTYPE # member type - self.linkname = "" # link name - self.uname = "" # user name - self.gname = "" # group name - self.devmajor = 0 # device major number - self.devminor = 0 # device minor number - - self.offset = 0 # the tar header starts here - self.offset_data = 0 # the file's data starts here - - self.sparse = None # sparse member information - self.pax_headers = {} # pax header information - - # In pax headers the "name" and "linkname" field are called - # "path" and "linkpath". - @property - def path(self): - return self.name - - @path.setter - def path(self, name): - self.name = name - - @property - def linkpath(self): - return self.linkname - - @linkpath.setter - def linkpath(self, linkname): - self.linkname = linkname - - def __repr__(self): - return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) - - def get_info(self): - """Return the TarInfo's attributes as a dictionary. - """ - info = { - "name": self.name, - "mode": self.mode & 0o7777, - "uid": self.uid, - "gid": self.gid, - "size": self.size, - "mtime": self.mtime, - "chksum": self.chksum, - "type": self.type, - "linkname": self.linkname, - "uname": self.uname, - "gname": self.gname, - "devmajor": self.devmajor, - "devminor": self.devminor - } - - if info["type"] == DIRTYPE and not info["name"].endswith("/"): - info["name"] += "/" - - return info - - def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): - """Return a tar header as a string of 512 byte blocks. - """ - info = self.get_info() - - if format == USTAR_FORMAT: - return self.create_ustar_header(info, encoding, errors) - elif format == GNU_FORMAT: - return self.create_gnu_header(info, encoding, errors) - elif format == PAX_FORMAT: - return self.create_pax_header(info, encoding) - else: - raise ValueError("invalid format") - - def create_ustar_header(self, info, encoding, errors): - """Return the object as a ustar header block. - """ - info["magic"] = POSIX_MAGIC - - if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK: - raise ValueError("linkname is too long") - - if len(info["name"].encode(encoding, errors)) > LENGTH_NAME: - info["prefix"], info["name"] = self._posix_split_name(info["name"], encoding, errors) - - return self._create_header(info, USTAR_FORMAT, encoding, errors) - - def create_gnu_header(self, info, encoding, errors): - """Return the object as a GNU header block sequence. - """ - info["magic"] = GNU_MAGIC - - buf = b"" - if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK: - buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) - - if len(info["name"].encode(encoding, errors)) > LENGTH_NAME: - buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) - - return buf + self._create_header(info, GNU_FORMAT, encoding, errors) - - def create_pax_header(self, info, encoding): - """Return the object as a ustar header block. If it cannot be - represented this way, prepend a pax extended header sequence - with supplement information. - """ - info["magic"] = POSIX_MAGIC - pax_headers = self.pax_headers.copy() - - # Test string fields for values that exceed the field length or cannot - # be represented in ASCII encoding. - for name, hname, length in ( - ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), - ("uname", "uname", 32), ("gname", "gname", 32)): - - if hname in pax_headers: - # The pax header has priority. - continue - - # Try to encode the string as ASCII. - try: - info[name].encode("ascii", "strict") - except UnicodeEncodeError: - pax_headers[hname] = info[name] - continue - - if len(info[name]) > length: - pax_headers[hname] = info[name] - - # Test number fields for values that exceed the field limit or values - # that like to be stored as float. - for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): - if name in pax_headers: - # The pax header has priority. Avoid overflow. - info[name] = 0 - continue - - val = info[name] - if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): - pax_headers[name] = str(val) - info[name] = 0 - - # Create a pax extended header if necessary. - if pax_headers: - buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) - else: - buf = b"" - - return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") - - @classmethod - def create_pax_global_header(cls, pax_headers): - """Return the object as a pax global header block sequence. - """ - return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf-8") - - def _posix_split_name(self, name, encoding, errors): - """Split a name longer than 100 chars into a prefix - and a name part. - """ - components = name.split("/") - for i in range(1, len(components)): - prefix = "/".join(components[:i]) - name = "/".join(components[i:]) - if len(prefix.encode(encoding, errors)) <= LENGTH_PREFIX and \ - len(name.encode(encoding, errors)) <= LENGTH_NAME: - break - else: - raise ValueError("name is too long") - - return prefix, name - - @staticmethod - def _create_header(info, format, encoding, errors): - """Return a header block. info is a dictionary with file - information, format must be one of the *_FORMAT constants. - """ - parts = [ - stn(info.get("name", ""), 100, encoding, errors), - itn(info.get("mode", 0) & 0o7777, 8, format), - itn(info.get("uid", 0), 8, format), - itn(info.get("gid", 0), 8, format), - itn(info.get("size", 0), 12, format), - itn(info.get("mtime", 0), 12, format), - b" ", # checksum field - info.get("type", REGTYPE), - stn(info.get("linkname", ""), 100, encoding, errors), - info.get("magic", POSIX_MAGIC), - stn(info.get("uname", ""), 32, encoding, errors), - stn(info.get("gname", ""), 32, encoding, errors), - itn(info.get("devmajor", 0), 8, format), - itn(info.get("devminor", 0), 8, format), - stn(info.get("prefix", ""), 155, encoding, errors) - ] - - buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) - chksum = calc_chksums(buf[-BLOCKSIZE:])[0] - buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:] - return buf - - @staticmethod - def _create_payload(payload): - """Return the string payload filled with zero bytes - up to the next 512 byte border. - """ - blocks, remainder = divmod(len(payload), BLOCKSIZE) - if remainder > 0: - payload += (BLOCKSIZE - remainder) * NUL - return payload - - @classmethod - def _create_gnu_long_header(cls, name, type, encoding, errors): - """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence - for name. - """ - name = name.encode(encoding, errors) + NUL - - info = {} - info["name"] = "././@LongLink" - info["type"] = type - info["size"] = len(name) - info["magic"] = GNU_MAGIC - - # create extended header + name blocks. - return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ - cls._create_payload(name) - - @classmethod - def _create_pax_generic_header(cls, pax_headers, type, encoding): - """Return a POSIX.1-2008 extended or global header sequence - that contains a list of keyword, value pairs. The values - must be strings. - """ - # Check if one of the fields contains surrogate characters and thereby - # forces hdrcharset=BINARY, see _proc_pax() for more information. - binary = False - for keyword, value in pax_headers.items(): - try: - value.encode("utf-8", "strict") - except UnicodeEncodeError: - binary = True - break - - records = b"" - if binary: - # Put the hdrcharset field at the beginning of the header. - records += b"21 hdrcharset=BINARY\n" - - for keyword, value in pax_headers.items(): - keyword = keyword.encode("utf-8") - if binary: - # Try to restore the original byte representation of `value'. - # Needless to say, that the encoding must match the string. - value = value.encode(encoding, "surrogateescape") - else: - value = value.encode("utf-8") - - l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' - n = p = 0 - while True: - n = l + len(str(p)) - if n == p: - break - p = n - records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" - - # We use a hardcoded "././@PaxHeader" name like star does - # instead of the one that POSIX recommends. - info = {} - info["name"] = "././@PaxHeader" - info["type"] = type - info["size"] = len(records) - info["magic"] = POSIX_MAGIC - - # Create pax header + record blocks. - return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ - cls._create_payload(records) - - @classmethod - def frombuf(cls, buf, encoding, errors): - """Construct a TarInfo object from a 512 byte bytes object. - """ - if len(buf) == 0: - raise EmptyHeaderError("empty header") - if len(buf) != BLOCKSIZE: - raise TruncatedHeaderError("truncated header") - if buf.count(NUL) == BLOCKSIZE: - raise EOFHeaderError("end of file header") - - chksum = nti(buf[148:156]) - if chksum not in calc_chksums(buf): - raise InvalidHeaderError("bad checksum") - - obj = cls() - obj.name = nts(buf[0:100], encoding, errors) - obj.mode = nti(buf[100:108]) - obj.uid = nti(buf[108:116]) - obj.gid = nti(buf[116:124]) - obj.size = nti(buf[124:136]) - obj.mtime = nti(buf[136:148]) - obj.chksum = chksum - obj.type = buf[156:157] - obj.linkname = nts(buf[157:257], encoding, errors) - obj.uname = nts(buf[265:297], encoding, errors) - obj.gname = nts(buf[297:329], encoding, errors) - obj.devmajor = nti(buf[329:337]) - obj.devminor = nti(buf[337:345]) - prefix = nts(buf[345:500], encoding, errors) - - # Old V7 tar format represents a directory as a regular - # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): - obj.type = DIRTYPE - - # The old GNU sparse format occupies some of the unused - # space in the buffer for up to 4 sparse structures. - # Save them for later processing in _proc_sparse(). - if obj.type == GNUTYPE_SPARSE: - pos = 386 - structs = [] - for i in range(4): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[482]) - origsize = nti(buf[483:495]) - obj._sparse_structs = (structs, isextended, origsize) - - # Remove redundant slashes from directories. - if obj.isdir(): - obj.name = obj.name.rstrip("/") - - # Reconstruct a ustar longname. - if prefix and obj.type not in GNU_TYPES: - obj.name = prefix + "/" + obj.name - return obj - - @classmethod - def fromtarfile(cls, tarfile): - """Return the next TarInfo object from TarFile object - tarfile. - """ - buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) - obj.offset = tarfile.fileobj.tell() - BLOCKSIZE - return obj._proc_member(tarfile) - - #-------------------------------------------------------------------------- - # The following are methods that are called depending on the type of a - # member. The entry point is _proc_member() which can be overridden in a - # subclass to add custom _proc_*() methods. A _proc_*() method MUST - # implement the following - # operations: - # 1. Set self.offset_data to the position where the data blocks begin, - # if there is data that follows. - # 2. Set tarfile.offset to the position where the next member's header will - # begin. - # 3. Return self or another valid TarInfo object. - def _proc_member(self, tarfile): - """Choose the right processing method depending on - the type and call it. - """ - if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - return self._proc_gnulong(tarfile) - elif self.type == GNUTYPE_SPARSE: - return self._proc_sparse(tarfile) - elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): - return self._proc_pax(tarfile) - else: - return self._proc_builtin(tarfile) - - def _proc_builtin(self, tarfile): - """Process a builtin type or an unknown type which - will be treated as a regular file. - """ - self.offset_data = tarfile.fileobj.tell() - offset = self.offset_data - if self.isreg() or self.type not in SUPPORTED_TYPES: - # Skip the following data blocks. - offset += self._block(self.size) - tarfile.offset = offset - - # Patch the TarInfo object with saved global - # header information. - self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) - - return self - - def _proc_gnulong(self, tarfile): - """Process the blocks that hold a GNU longname - or longlink member. - """ - buf = tarfile.fileobj.read(self._block(self.size)) - - # Fetch the next header and process it. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Patch the TarInfo object from the next header with - # the longname information. - next.offset = self.offset - if self.type == GNUTYPE_LONGNAME: - next.name = nts(buf, tarfile.encoding, tarfile.errors) - elif self.type == GNUTYPE_LONGLINK: - next.linkname = nts(buf, tarfile.encoding, tarfile.errors) - - return next - - def _proc_sparse(self, tarfile): - """Process a GNU sparse header plus extra headers. - """ - # We already collected some sparse structures in frombuf(). - structs, isextended, origsize = self._sparse_structs - del self._sparse_structs - - # Collect sparse structures from extended header blocks. - while isextended: - buf = tarfile.fileobj.read(BLOCKSIZE) - pos = 0 - for i in range(21): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset and numbytes: - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[504]) - self.sparse = structs - - self.offset_data = tarfile.fileobj.tell() - tarfile.offset = self.offset_data + self._block(self.size) - self.size = origsize - return self - - def _proc_pax(self, tarfile): - """Process an extended or global header as described in - POSIX.1-2008. - """ - # Read the header information. - buf = tarfile.fileobj.read(self._block(self.size)) - - # A pax header stores supplemental information for either - # the following file (extended) or all following files - # (global). - if self.type == XGLTYPE: - pax_headers = tarfile.pax_headers - else: - pax_headers = tarfile.pax_headers.copy() - - # Check if the pax header contains a hdrcharset field. This tells us - # the encoding of the path, linkpath, uname and gname fields. Normally, - # these fields are UTF-8 encoded but since POSIX.1-2008 tar - # implementations are allowed to store them as raw binary strings if - # the translation to UTF-8 fails. - match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) - if match is not None: - pax_headers["hdrcharset"] = match.group(1).decode("utf-8") - - # For the time being, we don't care about anything other than "BINARY". - # The only other value that is currently allowed by the standard is - # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. - hdrcharset = pax_headers.get("hdrcharset") - if hdrcharset == "BINARY": - encoding = tarfile.encoding - else: - encoding = "utf-8" - - # Parse pax header information. A record looks like that: - # "%d %s=%s\n" % (length, keyword, value). length is the size - # of the complete record including the length field itself and - # the newline. keyword and value are both UTF-8 encoded strings. - regex = re.compile(br"(\d+) ([^=]+)=") - pos = 0 - while True: - match = regex.match(buf, pos) - if not match: - break - - length, keyword = match.groups() - length = int(length) - value = buf[match.end(2) + 1:match.start(1) + length - 1] - - # Normally, we could just use "utf-8" as the encoding and "strict" - # as the error handler, but we better not take the risk. For - # example, GNU tar <= 1.23 is known to store filenames it cannot - # translate to UTF-8 as raw strings (unfortunately without a - # hdrcharset=BINARY header). - # We first try the strict standard encoding, and if that fails we - # fall back on the user's encoding and error handler. - keyword = self._decode_pax_field(keyword, "utf-8", "utf-8", - tarfile.errors) - if keyword in PAX_NAME_FIELDS: - value = self._decode_pax_field(value, encoding, tarfile.encoding, - tarfile.errors) - else: - value = self._decode_pax_field(value, "utf-8", "utf-8", - tarfile.errors) - - pax_headers[keyword] = value - pos += length - - # Fetch the next header. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Process GNU sparse information. - if "GNU.sparse.map" in pax_headers: - # GNU extended sparse format version 0.1. - self._proc_gnusparse_01(next, pax_headers) - - elif "GNU.sparse.size" in pax_headers: - # GNU extended sparse format version 0.0. - self._proc_gnusparse_00(next, pax_headers, buf) - - elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": - # GNU extended sparse format version 1.0. - self._proc_gnusparse_10(next, pax_headers, tarfile) - - if self.type in (XHDTYPE, SOLARIS_XHDTYPE): - # Patch the TarInfo object with the extended header info. - next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) - next.offset = self.offset - - if "size" in pax_headers: - # If the extended header replaces the size field, - # we need to recalculate the offset where the next - # header starts. - offset = next.offset_data - if next.isreg() or next.type not in SUPPORTED_TYPES: - offset += next._block(next.size) - tarfile.offset = offset - - return next - - def _proc_gnusparse_00(self, next, pax_headers, buf): - """Process a GNU tar extended sparse header, version 0.0. - """ - offsets = [] - for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): - offsets.append(int(match.group(1))) - numbytes = [] - for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): - numbytes.append(int(match.group(1))) - next.sparse = list(zip(offsets, numbytes)) - - def _proc_gnusparse_01(self, next, pax_headers): - """Process a GNU tar extended sparse header, version 0.1. - """ - sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _proc_gnusparse_10(self, next, pax_headers, tarfile): - """Process a GNU tar extended sparse header, version 1.0. - """ - fields = None - sparse = [] - buf = tarfile.fileobj.read(BLOCKSIZE) - fields, buf = buf.split(b"\n", 1) - fields = int(fields) - while len(sparse) < fields * 2: - if b"\n" not in buf: - buf += tarfile.fileobj.read(BLOCKSIZE) - number, buf = buf.split(b"\n", 1) - sparse.append(int(number)) - next.offset_data = tarfile.fileobj.tell() - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _apply_pax_info(self, pax_headers, encoding, errors): - """Replace fields with supplemental information from a previous - pax extended or global header. - """ - for keyword, value in pax_headers.items(): - if keyword == "GNU.sparse.name": - setattr(self, "path", value) - elif keyword == "GNU.sparse.size": - setattr(self, "size", int(value)) - elif keyword == "GNU.sparse.realsize": - setattr(self, "size", int(value)) - elif keyword in PAX_FIELDS: - if keyword in PAX_NUMBER_FIELDS: - try: - value = PAX_NUMBER_FIELDS[keyword](value) - except ValueError: - value = 0 - if keyword == "path": - value = value.rstrip("/") - setattr(self, keyword, value) - - self.pax_headers = pax_headers.copy() - - def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): - """Decode a single field from a pax record. - """ - try: - return value.decode(encoding, "strict") - except UnicodeDecodeError: - return value.decode(fallback_encoding, fallback_errors) - - def _block(self, count): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 - return blocks * BLOCKSIZE - - def isreg(self): - return self.type in REGULAR_TYPES - def isfile(self): - return self.isreg() - def isdir(self): - return self.type == DIRTYPE - def issym(self): - return self.type == SYMTYPE - def islnk(self): - return self.type == LNKTYPE - def ischr(self): - return self.type == CHRTYPE - def isblk(self): - return self.type == BLKTYPE - def isfifo(self): - return self.type == FIFOTYPE - def issparse(self): - return self.sparse is not None - def isdev(self): - return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) -# class TarInfo - -class TarFile(object): - """The TarFile Class provides an interface to tar archives. - """ - - debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) - - dereference = False # If true, add content of linked file to the - # tar file, else the link. - - ignore_zeros = False # If true, skips empty or invalid blocks and - # continues processing. - - errorlevel = 1 # If 0, fatal errors only appear in debug - # messages (if debug >= 0). If > 0, errors - # are passed to the caller as exceptions. - - format = DEFAULT_FORMAT # The format to use when creating an archive. - - encoding = ENCODING # Encoding for 8-bit character strings. - - errors = None # Error handler for unicode conversion. - - tarinfo = TarInfo # The default TarInfo class to use. - - fileobject = ExFileObject # The file-object for extractfile(). - - def __init__(self, name=None, mode="r", fileobj=None, format=None, - tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, - errors="surrogateescape", pax_headers=None, debug=None, - errorlevel=None, copybufsize=None): - """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to - read from an existing archive, 'a' to append data to an existing - file or 'w' to create a new file overwriting an existing one. `mode' - defaults to 'r'. - If `fileobj' is given, it is used for reading or writing data. If it - can be determined, `mode' is overridden by `fileobj's mode. - `fileobj' is not closed, when TarFile is closed. - """ - modes = {"r": "rb", "a": "r+b", "w": "wb", "x": "xb"} - if mode not in modes: - raise ValueError("mode must be 'r', 'a', 'w' or 'x'") - self.mode = mode - self._mode = modes[mode] - - if not fileobj: - if self.mode == "a" and not os.path.exists(name): - # Create nonexistent files in append mode. - self.mode = "w" - self._mode = "wb" - fileobj = bltn_open(name, self._mode) - self._extfileobj = False - else: - if (name is None and hasattr(fileobj, "name") and - isinstance(fileobj.name, (str, bytes))): - name = fileobj.name - if hasattr(fileobj, "mode"): - self._mode = fileobj.mode - self._extfileobj = True - self.name = os.path.abspath(name) if name else None - self.fileobj = fileobj - - # Init attributes. - if format is not None: - self.format = format - if tarinfo is not None: - self.tarinfo = tarinfo - if dereference is not None: - self.dereference = dereference - if ignore_zeros is not None: - self.ignore_zeros = ignore_zeros - if encoding is not None: - self.encoding = encoding - self.errors = errors - - if pax_headers is not None and self.format == PAX_FORMAT: - self.pax_headers = pax_headers - else: - self.pax_headers = {} - - if debug is not None: - self.debug = debug - if errorlevel is not None: - self.errorlevel = errorlevel - - # Init datastructures. - self.copybufsize = copybufsize - self.closed = False - self.members = [] # list of members as TarInfo objects - self._loaded = False # flag if all members have been read - self.offset = self.fileobj.tell() - # current position in the archive file - self.inodes = {} # dictionary caching the inodes of - # archive members already added - - try: - if self.mode == "r": - self.firstmember = None - self.firstmember = self.next() - - if self.mode == "a": - # Move to the end of the archive, - # before the first empty block. - while True: - self.fileobj.seek(self.offset) - try: - tarinfo = self.tarinfo.fromtarfile(self) - self.members.append(tarinfo) - except EOFHeaderError: - self.fileobj.seek(self.offset) - break - except HeaderError as e: - raise ReadError(str(e)) - - if self.mode in ("a", "w", "x"): - self._loaded = True - - if self.pax_headers: - buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) - self.fileobj.write(buf) - self.offset += len(buf) - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - #-------------------------------------------------------------------------- - # Below are the classmethods which act as alternate constructors to the - # TarFile class. The open() method is the only one that is needed for - # public use; it is the "super"-constructor and is able to select an - # adequate "sub"-constructor for a particular compression using the mapping - # from OPEN_METH. - # - # This concept allows one to subclass TarFile without losing the comfort of - # the super-constructor. A sub-constructor is registered and made available - # by adding it to the mapping in OPEN_METH. - - @classmethod - def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): - """Open a tar archive for reading, writing or appending. Return - an appropriate TarFile class. - - mode: - 'r' or 'r:*' open for reading with transparent compression - 'r:' open for reading exclusively uncompressed - 'r:gz' open for reading with gzip compression - 'r:bz2' open for reading with bzip2 compression - 'r:xz' open for reading with lzma compression - 'a' or 'a:' open for appending, creating the file if necessary - 'w' or 'w:' open for writing without compression - 'w:gz' open for writing with gzip compression - 'w:bz2' open for writing with bzip2 compression - 'w:xz' open for writing with lzma compression - - 'x' or 'x:' create a tarfile exclusively without compression, raise - an exception if the file is already created - 'x:gz' create a gzip compressed tarfile, raise an exception - if the file is already created - 'x:bz2' create a bzip2 compressed tarfile, raise an exception - if the file is already created - 'x:xz' create an lzma compressed tarfile, raise an exception - if the file is already created - - 'r|*' open a stream of tar blocks with transparent compression - 'r|' open an uncompressed stream of tar blocks for reading - 'r|gz' open a gzip compressed stream of tar blocks - 'r|bz2' open a bzip2 compressed stream of tar blocks - 'r|xz' open an lzma compressed stream of tar blocks - 'w|' open an uncompressed stream for writing - 'w|gz' open a gzip compressed stream for writing - 'w|bz2' open a bzip2 compressed stream for writing - 'w|xz' open an lzma compressed stream for writing - """ - - if not name and not fileobj: - raise ValueError("nothing to open") - - if mode in ("r", "r:*"): - # Find out which *open() is appropriate for opening the file. - def not_compressed(comptype): - return cls.OPEN_METH[comptype] == 'taropen' - for comptype in sorted(cls.OPEN_METH, key=not_compressed): - func = getattr(cls, cls.OPEN_METH[comptype]) - if fileobj is not None: - saved_pos = fileobj.tell() - try: - return func(name, "r", fileobj, **kwargs) - except (ReadError, CompressionError): - if fileobj is not None: - fileobj.seek(saved_pos) - continue - raise ReadError("file could not be opened successfully") - - elif ":" in mode: - filemode, comptype = mode.split(":", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - # Select the *open() function according to - # given compression. - if comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - else: - raise CompressionError("unknown compression type %r" % comptype) - return func(name, filemode, fileobj, **kwargs) - - elif "|" in mode: - filemode, comptype = mode.split("|", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - if filemode not in ("r", "w"): - raise ValueError("mode must be 'r' or 'w'") - - stream = _Stream(name, filemode, comptype, fileobj, bufsize) - try: - t = cls(name, filemode, stream, **kwargs) - except: - stream.close() - raise - t._extfileobj = False - return t - - elif mode in ("a", "w", "x"): - return cls.taropen(name, mode, fileobj, **kwargs) - - raise ValueError("undiscernible mode") - - @classmethod - def taropen(cls, name, mode="r", fileobj=None, **kwargs): - """Open uncompressed tar archive name for reading or writing. - """ - if mode not in ("r", "a", "w", "x"): - raise ValueError("mode must be 'r', 'a', 'w' or 'x'") - return cls(name, mode, fileobj, **kwargs) - - @classmethod - def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open gzip compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if mode not in ("r", "w", "x"): - raise ValueError("mode must be 'r', 'w' or 'x'") - - try: - from gzip import GzipFile - except ImportError: - raise CompressionError("gzip module is not available") - - try: - fileobj = GzipFile(name, mode + "b", compresslevel, fileobj) - except OSError: - if fileobj is not None and mode == 'r': - raise ReadError("not a gzip file") - raise - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except OSError: - fileobj.close() - if mode == 'r': - raise ReadError("not a gzip file") - raise - except: - fileobj.close() - raise - t._extfileobj = False - return t - - @classmethod - def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open bzip2 compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if mode not in ("r", "w", "x"): - raise ValueError("mode must be 'r', 'w' or 'x'") - - try: - from bz2 import BZ2File - except ImportError: - raise CompressionError("bz2 module is not available") - - fileobj = BZ2File(fileobj or name, mode, compresslevel=compresslevel) - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except (OSError, EOFError): - fileobj.close() - if mode == 'r': - raise ReadError("not a bzip2 file") - raise - except: - fileobj.close() - raise - t._extfileobj = False - return t - - @classmethod - def xzopen(cls, name, mode="r", fileobj=None, preset=None, **kwargs): - """Open lzma compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if mode not in ("r", "w", "x"): - raise ValueError("mode must be 'r', 'w' or 'x'") - - try: - from lzma import LZMAFile, LZMAError - except ImportError: - raise CompressionError("lzma module is not available") - - fileobj = LZMAFile(fileobj or name, mode, preset=preset) - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except (LZMAError, EOFError): - fileobj.close() - if mode == 'r': - raise ReadError("not an lzma file") - raise - except: - fileobj.close() - raise - t._extfileobj = False - return t - - # All *open() methods are registered here. - OPEN_METH = { - "tar": "taropen", # uncompressed tar - "gz": "gzopen", # gzip compressed tar - "bz2": "bz2open", # bzip2 compressed tar - "xz": "xzopen" # lzma compressed tar - } - - #-------------------------------------------------------------------------- - # The public methods which TarFile provides: - - def close(self): - """Close the TarFile. In write-mode, two finishing zero blocks are - appended to the archive. - """ - if self.closed: - return - - self.closed = True - try: - if self.mode in ("a", "w", "x"): - self.fileobj.write(NUL * (BLOCKSIZE * 2)) - self.offset += (BLOCKSIZE * 2) - # fill up the end with zero-blocks - # (like option -b20 for tar does) - blocks, remainder = divmod(self.offset, RECORDSIZE) - if remainder > 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - finally: - if not self._extfileobj: - self.fileobj.close() - - def getmember(self, name): - """Return a TarInfo object for member `name'. If `name' can not be - found in the archive, KeyError is raised. If a member occurs more - than once in the archive, its last occurrence is assumed to be the - most up-to-date version. - """ - tarinfo = self._getmember(name) - if tarinfo is None: - raise KeyError("filename %r not found" % name) - return tarinfo - - def getmembers(self): - """Return the members of the archive as a list of TarInfo objects. The - list has the same order as the members in the archive. - """ - self._check() - if not self._loaded: # if we want to obtain a list of - self._load() # all members, we first have to - # scan the whole archive. - return self.members - - def getnames(self): - """Return the members of the archive as a list of their names. It has - the same order as the list returned by getmembers(). - """ - return [tarinfo.name for tarinfo in self.getmembers()] - - def gettarinfo(self, name=None, arcname=None, fileobj=None): - """Create a TarInfo object from the result of os.stat or equivalent - on an existing file. The file is either named by `name', or - specified as a file object `fileobj' with a file descriptor. If - given, `arcname' specifies an alternative name for the file in the - archive, otherwise, the name is taken from the 'name' attribute of - 'fileobj', or the 'name' argument. The name should be a text - string. - """ - self._check("awx") - - # When fileobj is given, replace name by - # fileobj's real name. - if fileobj is not None: - name = fileobj.name - - # Building the name of the member in the archive. - # Backward slashes are converted to forward slashes, - # Absolute paths are turned to relative paths. - if arcname is None: - arcname = name - drv, arcname = os.path.splitdrive(arcname) - arcname = arcname.replace(os.sep, "/") - arcname = arcname.lstrip("/") - - # Now, fill the TarInfo object with - # information specific for the file. - tarinfo = self.tarinfo() - tarinfo.tarfile = self # Not needed - - # Use os.stat or os.lstat, depending on platform - # and if symlinks shall be resolved. - if fileobj is None: - if hasattr(os, "lstat") and not self.dereference: - statres = os.lstat(name) - else: - statres = os.stat(name) - else: - statres = os.fstat(fileobj.fileno()) - linkname = "" - - stmd = statres.st_mode - if stat.S_ISREG(stmd): - inode = (statres.st_ino, statres.st_dev) - if not self.dereference and statres.st_nlink > 1 and \ - inode in self.inodes and arcname != self.inodes[inode]: - # Is it a hardlink to an already - # archived file? - type = LNKTYPE - linkname = self.inodes[inode] - else: - # The inode is added only if its valid. - # For win32 it is always 0. - type = REGTYPE - if inode[0]: - self.inodes[inode] = arcname - elif stat.S_ISDIR(stmd): - type = DIRTYPE - elif stat.S_ISFIFO(stmd): - type = FIFOTYPE - elif stat.S_ISLNK(stmd): - type = SYMTYPE - linkname = os.readlink(name) - elif stat.S_ISCHR(stmd): - type = CHRTYPE - elif stat.S_ISBLK(stmd): - type = BLKTYPE - else: - return None - - # Fill the TarInfo object with all - # information we can get. - tarinfo.name = arcname - tarinfo.mode = stmd - tarinfo.uid = statres.st_uid - tarinfo.gid = statres.st_gid - if type == REGTYPE: - tarinfo.size = statres.st_size - else: - tarinfo.size = 0 - tarinfo.mtime = statres.st_mtime - tarinfo.type = type - tarinfo.linkname = linkname - if pwd: - try: - tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] - except KeyError: - pass - if grp: - try: - tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] - except KeyError: - pass - - if type in (CHRTYPE, BLKTYPE): - if hasattr(os, "major") and hasattr(os, "minor"): - tarinfo.devmajor = os.major(statres.st_rdev) - tarinfo.devminor = os.minor(statres.st_rdev) - return tarinfo - - def list(self, verbose=True, *, members=None): - """Print a table of contents to sys.stdout. If `verbose' is False, only - the names of the members are printed. If it is True, an `ls -l'-like - output is produced. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - self._check() - - if members is None: - members = self - for tarinfo in members: - if verbose: - _safe_print(stat.filemode(tarinfo.mode)) - _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid)) - if tarinfo.ischr() or tarinfo.isblk(): - _safe_print("%10s" % - ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor))) - else: - _safe_print("%10d" % tarinfo.size) - _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6]) - - _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else "")) - - if verbose: - if tarinfo.issym(): - _safe_print("-> " + tarinfo.linkname) - if tarinfo.islnk(): - _safe_print("link to " + tarinfo.linkname) - print() - - def add(self, name, arcname=None, recursive=True, *, filter=None): - """Add the file `name' to the archive. `name' may be any type of file - (directory, fifo, symbolic link, etc.). If given, `arcname' - specifies an alternative name for the file in the archive. - Directories are added recursively by default. This can be avoided by - setting `recursive' to False. `filter' is a function - that expects a TarInfo object argument and returns the changed - TarInfo object, if it returns None the TarInfo object will be - excluded from the archive. - """ - self._check("awx") - - if arcname is None: - arcname = name - - # Skip if somebody tries to archive the archive... - if self.name is not None and os.path.abspath(name) == self.name: - self._dbg(2, "tarfile: Skipped %r" % name) - return - - self._dbg(1, name) - - # Create a TarInfo object from the file. - tarinfo = self.gettarinfo(name, arcname) - - if tarinfo is None: - self._dbg(1, "tarfile: Unsupported type %r" % name) - return - - # Change or exclude the TarInfo object. - if filter is not None: - tarinfo = filter(tarinfo) - if tarinfo is None: - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Append the tar header and data to the archive. - if tarinfo.isreg(): - with bltn_open(name, "rb") as f: - self.addfile(tarinfo, f) - - elif tarinfo.isdir(): - self.addfile(tarinfo) - if recursive: - for f in sorted(os.listdir(name)): - self.add(os.path.join(name, f), os.path.join(arcname, f), - recursive, filter=filter) - - else: - self.addfile(tarinfo) - - def addfile(self, tarinfo, fileobj=None): - """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is - given, it should be a binary file, and tarinfo.size bytes are read - from it and added to the archive. You can create TarInfo objects - directly, or by using gettarinfo(). - """ - self._check("awx") - - tarinfo = copy.copy(tarinfo) - - buf = tarinfo.tobuf(self.format, self.encoding, self.errors) - self.fileobj.write(buf) - self.offset += len(buf) - bufsize=self.copybufsize - # If there's data to follow, append it. - if fileobj is not None: - copyfileobj(fileobj, self.fileobj, tarinfo.size, bufsize=bufsize) - blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) - if remainder > 0: - self.fileobj.write(NUL * (BLOCKSIZE - remainder)) - blocks += 1 - self.offset += blocks * BLOCKSIZE - - self.members.append(tarinfo) - - def extractall(self, path=".", members=None, *, numeric_owner=False): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). If `numeric_owner` is True, only - the numbers for user/group names are used and not the names. - """ - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 0o700 - # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir(), - numeric_owner=numeric_owner) - - # Reverse sort directories. - directories.sort(key=lambda a: a.name) - directories.reverse() - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath, numeric_owner=numeric_owner) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extract(self, member, path="", set_attrs=True, *, numeric_owner=False): - """Extract a member from the archive to the current working directory, - using its full name. Its file information is extracted as accurately - as possible. `member' may be a filename or a TarInfo object. You can - specify a different directory using `path'. File attributes (owner, - mtime, mode) are set unless `set_attrs' is False. If `numeric_owner` - is True, only the numbers for user/group names are used and not - the names. - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - # Prepare the link target for makelink(). - if tarinfo.islnk(): - tarinfo._link_target = os.path.join(path, tarinfo.linkname) - - try: - self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs, - numeric_owner=numeric_owner) - except OSError as e: - if self.errorlevel > 0: - raise - else: - if e.filename is None: - self._dbg(1, "tarfile: %s" % e.strerror) - else: - self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extractfile(self, member): - """Extract a member from the archive as a file object. `member' may be - a filename or a TarInfo object. If `member' is a regular file or a - link, an io.BufferedReader object is returned. Otherwise, None is - returned. - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES: - # Members with unknown types are treated as regular files. - return self.fileobject(self, tarinfo) - - elif tarinfo.islnk() or tarinfo.issym(): - if isinstance(self.fileobj, _Stream): - # A small but ugly workaround for the case that someone tries - # to extract a (sym)link as a file-object from a non-seekable - # stream of tar blocks. - raise StreamError("cannot extract (sym)link as file object") - else: - # A (sym)link's file object is its target's file object. - return self.extractfile(self._find_link_target(tarinfo)) - else: - # If there's no data associated with the member (directory, chrdev, - # blkdev, etc.), return None instead of a file object. - return None - - def _extract_member(self, tarinfo, targetpath, set_attrs=True, - numeric_owner=False): - """Extract the TarInfo object tarinfo to a physical - file called targetpath. - """ - # Fetch the TarInfo object for the given name - # and build the destination pathname, replacing - # forward slashes to platform specific separators. - targetpath = targetpath.rstrip("/") - targetpath = targetpath.replace("/", os.sep) - - # Create all upper directories. - upperdirs = os.path.dirname(targetpath) - if upperdirs and not os.path.exists(upperdirs): - # Create directories that are not part of the archive with - # default permissions. - os.makedirs(upperdirs) - - if tarinfo.islnk() or tarinfo.issym(): - self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) - else: - self._dbg(1, tarinfo.name) - - if tarinfo.isreg(): - self.makefile(tarinfo, targetpath) - elif tarinfo.isdir(): - self.makedir(tarinfo, targetpath) - elif tarinfo.isfifo(): - self.makefifo(tarinfo, targetpath) - elif tarinfo.ischr() or tarinfo.isblk(): - self.makedev(tarinfo, targetpath) - elif tarinfo.islnk() or tarinfo.issym(): - self.makelink(tarinfo, targetpath) - elif tarinfo.type not in SUPPORTED_TYPES: - self.makeunknown(tarinfo, targetpath) - else: - self.makefile(tarinfo, targetpath) - - if set_attrs: - self.chown(tarinfo, targetpath, numeric_owner) - if not tarinfo.issym(): - self.chmod(tarinfo, targetpath) - self.utime(tarinfo, targetpath) - - #-------------------------------------------------------------------------- - # Below are the different file methods. They are called via - # _extract_member() when extract() is called. They can be replaced in a - # subclass to implement other functionality. - - def makedir(self, tarinfo, targetpath): - """Make a directory called targetpath. - """ - try: - # Use a safe mode for the directory, the real mode is set - # later in _extract_member(). - os.mkdir(targetpath, 0o700) - except FileExistsError: - pass - - def makefile(self, tarinfo, targetpath): - """Make a file called targetpath. - """ - source = self.fileobj - source.seek(tarinfo.offset_data) - bufsize = self.copybufsize - with bltn_open(targetpath, "wb") as target: - if tarinfo.sparse is not None: - for offset, size in tarinfo.sparse: - target.seek(offset) - copyfileobj(source, target, size, ReadError, bufsize) - target.seek(tarinfo.size) - target.truncate() - else: - copyfileobj(source, target, tarinfo.size, ReadError, bufsize) - - def makeunknown(self, tarinfo, targetpath): - """Make a file from a TarInfo object with an unknown type - at targetpath. - """ - self.makefile(tarinfo, targetpath) - self._dbg(1, "tarfile: Unknown file type %r, " \ - "extracted as regular file." % tarinfo.type) - - def makefifo(self, tarinfo, targetpath): - """Make a fifo called targetpath. - """ - if hasattr(os, "mkfifo"): - os.mkfifo(targetpath) - else: - raise ExtractError("fifo not supported by system") - - def makedev(self, tarinfo, targetpath): - """Make a character or block device called targetpath. - """ - if not hasattr(os, "mknod") or not hasattr(os, "makedev"): - raise ExtractError("special devices not supported by system") - - mode = tarinfo.mode - if tarinfo.isblk(): - mode |= stat.S_IFBLK - else: - mode |= stat.S_IFCHR - - os.mknod(targetpath, mode, - os.makedev(tarinfo.devmajor, tarinfo.devminor)) - - def makelink(self, tarinfo, targetpath): - """Make a (symbolic) link called targetpath. If it cannot be created - (platform limitation), we try to make a copy of the referenced file - instead of a link. - """ - try: - # For systems that support symbolic and hard links. - if tarinfo.issym(): - os.symlink(tarinfo.linkname, targetpath) - else: - # See extract(). - if os.path.exists(tarinfo._link_target): - os.link(tarinfo._link_target, targetpath) - else: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except symlink_exception: - try: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except KeyError: - raise ExtractError("unable to resolve link inside archive") - - def chown(self, tarinfo, targetpath, numeric_owner): - """Set owner of targetpath according to tarinfo. If numeric_owner - is True, use .gid/.uid instead of .gname/.uname. If numeric_owner - is False, fall back to .gid/.uid when the search based on name - fails. - """ - if hasattr(os, "geteuid") and os.geteuid() == 0: - # We have to be root to do so. - g = tarinfo.gid - u = tarinfo.uid - if not numeric_owner: - try: - if grp: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: - pass - try: - if pwd: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: - pass - try: - if tarinfo.issym() and hasattr(os, "lchown"): - os.lchown(targetpath, u, g) - else: - os.chown(targetpath, u, g) - except OSError: - raise ExtractError("could not change owner") - - def chmod(self, tarinfo, targetpath): - """Set file permissions of targetpath according to tarinfo. - """ - if hasattr(os, 'chmod'): - try: - os.chmod(targetpath, tarinfo.mode) - except OSError: - raise ExtractError("could not change mode") - - def utime(self, tarinfo, targetpath): - """Set modification time of targetpath according to tarinfo. - """ - if not hasattr(os, 'utime'): - return - try: - os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) - except OSError: - raise ExtractError("could not change modification time") - - #-------------------------------------------------------------------------- - def next(self): - """Return the next member of the archive as a TarInfo object, when - TarFile is opened for reading. Return None if there is no more - available. - """ - self._check("ra") - if self.firstmember is not None: - m = self.firstmember - self.firstmember = None - return m - - # Advance the file pointer. - if self.offset != self.fileobj.tell(): - self.fileobj.seek(self.offset - 1) - if not self.fileobj.read(1): - raise ReadError("unexpected end of data") - - # Read the next block. - tarinfo = None - while True: - try: - tarinfo = self.tarinfo.fromtarfile(self) - except EOFHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - except InvalidHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - elif self.offset == 0: - raise ReadError(str(e)) - except EmptyHeaderError: - if self.offset == 0: - raise ReadError("empty file") - except TruncatedHeaderError as e: - if self.offset == 0: - raise ReadError(str(e)) - except SubsequentHeaderError as e: - raise ReadError(str(e)) - break - - if tarinfo is not None: - self.members.append(tarinfo) - else: - self._loaded = True - - return tarinfo - - #-------------------------------------------------------------------------- - # Little helper methods: - - def _getmember(self, name, tarinfo=None, normalize=False): - """Find an archive member by name from bottom to top. - If tarinfo is given, it is used as the starting point. - """ - # Ensure that all members have been loaded. - members = self.getmembers() - - # Limit the member search list up to tarinfo. - if tarinfo is not None: - members = members[:members.index(tarinfo)] - - if normalize: - name = os.path.normpath(name) - - for member in reversed(members): - if normalize: - member_name = os.path.normpath(member.name) - else: - member_name = member.name - - if name == member_name: - return member - - def _load(self): - """Read through the entire archive file and look for readable - members. - """ - while True: - tarinfo = self.next() - if tarinfo is None: - break - self._loaded = True - - def _check(self, mode=None): - """Check if TarFile is still open, and if the operation's mode - corresponds to TarFile's mode. - """ - if self.closed: - raise OSError("%s is closed" % self.__class__.__name__) - if mode is not None and self.mode not in mode: - raise OSError("bad operation for mode %r" % self.mode) - - def _find_link_target(self, tarinfo): - """Find the target member of a symlink or hardlink member in the - archive. - """ - if tarinfo.issym(): - # Always search the entire archive. - linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname))) - limit = None - else: - # Search the archive before the link, because a hard link is - # just a reference to an already archived file. - linkname = tarinfo.linkname - limit = tarinfo - - member = self._getmember(linkname, tarinfo=limit, normalize=True) - if member is None: - raise KeyError("linkname %r not found" % linkname) - return member - - def __iter__(self): - """Provide an iterator object. - """ - if self._loaded: - yield from self.members - return - - # Yield items using TarFile's next() method. - # When all members have been read, set TarFile as _loaded. - index = 0 - # Fix for SF #1100429: Under rare circumstances it can - # happen that getmembers() is called during iteration, - # which will have already exhausted the next() method. - if self.firstmember is not None: - tarinfo = self.next() - index += 1 - yield tarinfo - - while True: - if index < len(self.members): - tarinfo = self.members[index] - elif not self._loaded: - tarinfo = self.next() - if not tarinfo: - self._loaded = True - return - else: - return - index += 1 - yield tarinfo - - def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ - if level <= self.debug: - print(msg, file=sys.stderr) - - def __enter__(self): - self._check() - return self - - def __exit__(self, type, value, traceback): - if type is None: - self.close() - else: - # An exception occurred. We must not call close() because - # it would try to write end-of-archive blocks and padding. - if not self._extfileobj: - self.fileobj.close() - self.closed = True - -#-------------------- -# exported functions -#-------------------- -def is_tarfile(name): - """Return True if name points to a tar archive that we - are able to handle, else return False. - """ - try: - t = open(name) - t.close() - return True - except TarError: - return False - -open = TarFile.open - - -def main(): - import argparse - - description = 'A simple command-line interface for tarfile module.' - parser = argparse.ArgumentParser(description=description) - parser.add_argument('-v', '--verbose', action='store_true', default=False, - help='Verbose output') - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-l', '--list', metavar='', - help='Show listing of a tarfile') - group.add_argument('-e', '--extract', nargs='+', - metavar=('', ''), - help='Extract tarfile into target dir') - group.add_argument('-c', '--create', nargs='+', - metavar=('', ''), - help='Create tarfile from sources') - group.add_argument('-t', '--test', metavar='', - help='Test if a tarfile is valid') - args = parser.parse_args() - - if args.test is not None: - src = args.test - if is_tarfile(src): - with open(src, 'r') as tar: - tar.getmembers() - print(tar.getmembers(), file=sys.stderr) - if args.verbose: - print('{!r} is a tar archive.'.format(src)) - else: - parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) - - elif args.list is not None: - src = args.list - if is_tarfile(src): - with TarFile.open(src, 'r:*') as tf: - tf.list(verbose=args.verbose) - else: - parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) - - elif args.extract is not None: - if len(args.extract) == 1: - src = args.extract[0] - curdir = os.curdir - elif len(args.extract) == 2: - src, curdir = args.extract - else: - parser.exit(1, parser.format_help()) - - if is_tarfile(src): - with TarFile.open(src, 'r:*') as tf: - tf.extractall(path=curdir) - if args.verbose: - if curdir == '.': - msg = '{!r} file is extracted.'.format(src) - else: - msg = ('{!r} file is extracted ' - 'into {!r} directory.').format(src, curdir) - print(msg) - else: - parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) - - elif args.create is not None: - tar_name = args.create.pop(0) - _, ext = os.path.splitext(tar_name) - compressions = { - # gz - '.gz': 'gz', - '.tgz': 'gz', - # xz - '.xz': 'xz', - '.txz': 'xz', - # bz2 - '.bz2': 'bz2', - '.tbz': 'bz2', - '.tbz2': 'bz2', - '.tb2': 'bz2', - } - tar_mode = 'w:' + compressions[ext] if ext in compressions else 'w' - tar_files = args.create - - with TarFile.open(tar_name, tar_mode) as tf: - for file_name in tar_files: - tf.add(file_name) - - if args.verbose: - print('{!r} file created.'.format(tar_name)) - -if __name__ == '__main__': - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/tempfile.py b/experiment/simulation/backend/venv/lib/python3.7/tempfile.py deleted file mode 100644 index 24f673c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/tempfile.py +++ /dev/null @@ -1,811 +0,0 @@ -"""Temporary files. - -This module provides generic, low- and high-level interfaces for -creating temporary files and directories. All of the interfaces -provided by this module can be used without fear of race conditions -except for 'mktemp'. 'mktemp' is subject to race conditions and -should not be used; it is provided for backward compatibility only. - -The default path names are returned as str. If you supply bytes as -input, all return values will be in bytes. Ex: - - >>> tempfile.mkstemp() - (4, '/tmp/tmptpu9nin8') - >>> tempfile.mkdtemp(suffix=b'') - b'/tmp/tmppbi8f0hy' - -This module also provides some data items to the user: - - TMP_MAX - maximum number of names that will be tried before - giving up. - tempdir - If this is set to a string before the first use of - any routine from this module, it will be considered as - another candidate location to store temporary files. -""" - -__all__ = [ - "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces - "SpooledTemporaryFile", "TemporaryDirectory", - "mkstemp", "mkdtemp", # low level safe interfaces - "mktemp", # deprecated unsafe interface - "TMP_MAX", "gettempprefix", # constants - "tempdir", "gettempdir", - "gettempprefixb", "gettempdirb", - ] - - -# Imports. - -import functools as _functools -import warnings as _warnings -import io as _io -import os as _os -import shutil as _shutil -import errno as _errno -from random import Random as _Random -import weakref as _weakref -import _thread -_allocate_lock = _thread.allocate_lock - -_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL -if hasattr(_os, 'O_NOFOLLOW'): - _text_openflags |= _os.O_NOFOLLOW - -_bin_openflags = _text_openflags -if hasattr(_os, 'O_BINARY'): - _bin_openflags |= _os.O_BINARY - -if hasattr(_os, 'TMP_MAX'): - TMP_MAX = _os.TMP_MAX -else: - TMP_MAX = 10000 - -# This variable _was_ unused for legacy reasons, see issue 10354. -# But as of 3.5 we actually use it at runtime so changing it would -# have a possibly desirable side effect... But we do not want to support -# that as an API. It is undocumented on purpose. Do not depend on this. -template = "tmp" - -# Internal routines. - -_once_lock = _allocate_lock() - -if hasattr(_os, "lstat"): - _stat = _os.lstat -elif hasattr(_os, "stat"): - _stat = _os.stat -else: - # Fallback. All we need is something that raises OSError if the - # file doesn't exist. - def _stat(fn): - fd = _os.open(fn, _os.O_RDONLY) - _os.close(fd) - -def _exists(fn): - try: - _stat(fn) - except OSError: - return False - else: - return True - - -def _infer_return_type(*args): - """Look at the type of all args and divine their implied return type.""" - return_type = None - for arg in args: - if arg is None: - continue - if isinstance(arg, bytes): - if return_type is str: - raise TypeError("Can't mix bytes and non-bytes in " - "path components.") - return_type = bytes - else: - if return_type is bytes: - raise TypeError("Can't mix bytes and non-bytes in " - "path components.") - return_type = str - if return_type is None: - return str # tempfile APIs return a str by default. - return return_type - - -def _sanitize_params(prefix, suffix, dir): - """Common parameter processing for most APIs in this module.""" - output_type = _infer_return_type(prefix, suffix, dir) - if suffix is None: - suffix = output_type() - if prefix is None: - if output_type is str: - prefix = template - else: - prefix = _os.fsencode(template) - if dir is None: - if output_type is str: - dir = gettempdir() - else: - dir = gettempdirb() - return prefix, suffix, dir, output_type - - -class _RandomNameSequence: - """An instance of _RandomNameSequence generates an endless - sequence of unpredictable strings which can safely be incorporated - into file names. Each string is eight characters long. Multiple - threads can safely use the same instance at the same time. - - _RandomNameSequence is an iterator.""" - - characters = "abcdefghijklmnopqrstuvwxyz0123456789_" - - @property - def rng(self): - cur_pid = _os.getpid() - if cur_pid != getattr(self, '_rng_pid', None): - self._rng = _Random() - self._rng_pid = cur_pid - return self._rng - - def __iter__(self): - return self - - def __next__(self): - c = self.characters - choose = self.rng.choice - letters = [choose(c) for dummy in range(8)] - return ''.join(letters) - -def _candidate_tempdir_list(): - """Generate a list of candidate temporary directories which - _get_default_tempdir will try.""" - - dirlist = [] - - # First, try the environment. - for envname in 'TMPDIR', 'TEMP', 'TMP': - dirname = _os.getenv(envname) - if dirname: dirlist.append(dirname) - - # Failing that, try OS-specific locations. - if _os.name == 'nt': - dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), - _os.path.expandvars(r'%SYSTEMROOT%\Temp'), - r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) - else: - dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) - - # As a last resort, the current directory. - try: - dirlist.append(_os.getcwd()) - except (AttributeError, OSError): - dirlist.append(_os.curdir) - - return dirlist - -def _get_default_tempdir(): - """Calculate the default directory to use for temporary files. - This routine should be called exactly once. - - We determine whether or not a candidate temp dir is usable by - trying to create and write to a file in that directory. If this - is successful, the test file is deleted. To prevent denial of - service, the name of the test file must be randomized.""" - - namer = _RandomNameSequence() - dirlist = _candidate_tempdir_list() - - for dir in dirlist: - if dir != _os.curdir: - dir = _os.path.abspath(dir) - # Try only a few names per directory. - for seq in range(100): - name = next(namer) - filename = _os.path.join(dir, name) - try: - fd = _os.open(filename, _bin_openflags, 0o600) - try: - try: - with _io.open(fd, 'wb', closefd=False) as fp: - fp.write(b'blat') - finally: - _os.close(fd) - finally: - _os.unlink(filename) - return dir - except FileExistsError: - pass - except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): - continue - break # no point trying more names in this directory - except OSError: - break # no point trying more names in this directory - raise FileNotFoundError(_errno.ENOENT, - "No usable temporary directory found in %s" % - dirlist) - -_name_sequence = None - -def _get_candidate_names(): - """Common setup sequence for all user-callable interfaces.""" - - global _name_sequence - if _name_sequence is None: - _once_lock.acquire() - try: - if _name_sequence is None: - _name_sequence = _RandomNameSequence() - finally: - _once_lock.release() - return _name_sequence - - -def _mkstemp_inner(dir, pre, suf, flags, output_type): - """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" - - names = _get_candidate_names() - if output_type is bytes: - names = map(_os.fsencode, names) - - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, pre + name + suf) - try: - fd = _os.open(file, flags, 0o600) - except FileExistsError: - continue # try again - except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): - continue - else: - raise - return (fd, _os.path.abspath(file)) - - raise FileExistsError(_errno.EEXIST, - "No usable temporary file name found") - - -# User visible interfaces. - -def gettempprefix(): - """The default prefix for temporary directories.""" - return template - -def gettempprefixb(): - """The default prefix for temporary directories as bytes.""" - return _os.fsencode(gettempprefix()) - -tempdir = None - -def gettempdir(): - """Accessor for tempfile.tempdir.""" - global tempdir - if tempdir is None: - _once_lock.acquire() - try: - if tempdir is None: - tempdir = _get_default_tempdir() - finally: - _once_lock.release() - return tempdir - -def gettempdirb(): - """A bytes version of tempfile.gettempdir().""" - return _os.fsencode(gettempdir()) - -def mkstemp(suffix=None, prefix=None, dir=None, text=False): - """User-callable function to create and return a unique temporary - file. The return value is a pair (fd, name) where fd is the - file descriptor returned by os.open, and name is the filename. - - If 'suffix' is not None, the file name will end with that suffix, - otherwise there will be no suffix. - - If 'prefix' is not None, the file name will begin with that prefix, - otherwise a default prefix is used. - - If 'dir' is not None, the file will be created in that directory, - otherwise a default directory is used. - - If 'text' is specified and true, the file is opened in text - mode. Else (the default) the file is opened in binary mode. On - some operating systems, this makes no difference. - - If any of 'suffix', 'prefix' and 'dir' are not None, they must be the - same type. If they are bytes, the returned name will be bytes; str - otherwise. - - The file is readable and writable only by the creating user ID. - If the operating system uses permission bits to indicate whether a - file is executable, the file is executable by no one. The file - descriptor is not inherited by children of this process. - - Caller is responsible for deleting the file when done with it. - """ - - prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) - - if text: - flags = _text_openflags - else: - flags = _bin_openflags - - return _mkstemp_inner(dir, prefix, suffix, flags, output_type) - - -def mkdtemp(suffix=None, prefix=None, dir=None): - """User-callable function to create and return a unique temporary - directory. The return value is the pathname of the directory. - - Arguments are as for mkstemp, except that the 'text' argument is - not accepted. - - The directory is readable, writable, and searchable only by the - creating user. - - Caller is responsible for deleting the directory when done with it. - """ - - prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) - - names = _get_candidate_names() - if output_type is bytes: - names = map(_os.fsencode, names) - - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, prefix + name + suffix) - try: - _os.mkdir(file, 0o700) - except FileExistsError: - continue # try again - except PermissionError: - # This exception is thrown when a directory with the chosen name - # already exists on windows. - if (_os.name == 'nt' and _os.path.isdir(dir) and - _os.access(dir, _os.W_OK)): - continue - else: - raise - return file - - raise FileExistsError(_errno.EEXIST, - "No usable temporary directory name found") - -def mktemp(suffix="", prefix=template, dir=None): - """User-callable function to return a unique temporary file name. The - file is not created. - - Arguments are similar to mkstemp, except that the 'text' argument is - not accepted, and suffix=None, prefix=None and bytes file names are not - supported. - - THIS FUNCTION IS UNSAFE AND SHOULD NOT BE USED. The file name may - refer to a file that did not exist at some point, but by the time - you get around to creating it, someone else may have beaten you to - the punch. - """ - -## from warnings import warn as _warn -## _warn("mktemp is a potential security risk to your program", -## RuntimeWarning, stacklevel=2) - - if dir is None: - dir = gettempdir() - - names = _get_candidate_names() - for seq in range(TMP_MAX): - name = next(names) - file = _os.path.join(dir, prefix + name + suffix) - if not _exists(file): - return file - - raise FileExistsError(_errno.EEXIST, - "No usable temporary filename found") - - -class _TemporaryFileCloser: - """A separate object allowing proper closing of a temporary file's - underlying file object, without adding a __del__ method to the - temporary file.""" - - file = None # Set here since __del__ checks it - close_called = False - - def __init__(self, file, name, delete=True): - self.file = file - self.name = name - self.delete = delete - - # NT provides delete-on-close as a primitive, so we don't need - # the wrapper to do anything special. We still use it so that - # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. - if _os.name != 'nt': - # Cache the unlinker so we don't get spurious errors at - # shutdown when the module-level "os" is None'd out. Note - # that this must be referenced as self.unlink, because the - # name TemporaryFileWrapper may also get None'd out before - # __del__ is called. - - def close(self, unlink=_os.unlink): - if not self.close_called and self.file is not None: - self.close_called = True - try: - self.file.close() - finally: - if self.delete: - unlink(self.name) - - # Need to ensure the file is deleted on __del__ - def __del__(self): - self.close() - - else: - def close(self): - if not self.close_called: - self.close_called = True - self.file.close() - - -class _TemporaryFileWrapper: - """Temporary file wrapper - - This class provides a wrapper around files opened for - temporary use. In particular, it seeks to automatically - remove the file when it is no longer needed. - """ - - def __init__(self, file, name, delete=True): - self.file = file - self.name = name - self.delete = delete - self._closer = _TemporaryFileCloser(file, name, delete) - - def __getattr__(self, name): - # Attribute lookups are delegated to the underlying file - # and cached for non-numeric results - # (i.e. methods are cached, closed and friends are not) - file = self.__dict__['file'] - a = getattr(file, name) - if hasattr(a, '__call__'): - func = a - @_functools.wraps(func) - def func_wrapper(*args, **kwargs): - return func(*args, **kwargs) - # Avoid closing the file as long as the wrapper is alive, - # see issue #18879. - func_wrapper._closer = self._closer - a = func_wrapper - if not isinstance(a, int): - setattr(self, name, a) - return a - - # The underlying __enter__ method returns the wrong object - # (self.file) so override it to return the wrapper - def __enter__(self): - self.file.__enter__() - return self - - # Need to trap __exit__ as well to ensure the file gets - # deleted when used in a with statement - def __exit__(self, exc, value, tb): - result = self.file.__exit__(exc, value, tb) - self.close() - return result - - def close(self): - """ - Close the temporary file, possibly deleting it. - """ - self._closer.close() - - # iter() doesn't use __getattr__ to find the __iter__ method - def __iter__(self): - # Don't return iter(self.file), but yield from it to avoid closing - # file as long as it's being used as iterator (see issue #23700). We - # can't use 'yield from' here because iter(file) returns the file - # object itself, which has a close method, and thus the file would get - # closed when the generator is finalized, due to PEP380 semantics. - for line in self.file: - yield line - - -def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, - newline=None, suffix=None, prefix=None, - dir=None, delete=True): - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to io.open (default "w+b"). - 'buffering' -- the buffer size argument to io.open (default -1). - 'encoding' -- the encoding argument to io.open (default None) - 'newline' -- the newline argument to io.open (default None) - 'delete' -- whether the file is deleted on close (default True). - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface; the name of the file - is accessible as its 'name' attribute. The file will be automatically - deleted when it is closed unless the 'delete' argument is set to False. - """ - - prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) - - flags = _bin_openflags - - # Setting O_TEMPORARY in the flags causes the OS to delete - # the file when it is closed. This is only supported by Windows. - if _os.name == 'nt' and delete: - flags |= _os.O_TEMPORARY - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) - try: - file = _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) - - return _TemporaryFileWrapper(file, name, delete) - except BaseException: - _os.unlink(name) - _os.close(fd) - raise - -if _os.name != 'posix' or _os.sys.platform == 'cygwin': - # On non-POSIX and Cygwin systems, assume that we cannot unlink a file - # while it is open. - TemporaryFile = NamedTemporaryFile - -else: - # Is the O_TMPFILE flag available and does it work? - # The flag is set to False if os.open(dir, os.O_TMPFILE) raises an - # IsADirectoryError exception - _O_TMPFILE_WORKS = hasattr(_os, 'O_TMPFILE') - - def TemporaryFile(mode='w+b', buffering=-1, encoding=None, - newline=None, suffix=None, prefix=None, - dir=None): - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to io.open (default "w+b"). - 'buffering' -- the buffer size argument to io.open (default -1). - 'encoding' -- the encoding argument to io.open (default None) - 'newline' -- the newline argument to io.open (default None) - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface. The file has no - name, and will cease to exist when it is closed. - """ - global _O_TMPFILE_WORKS - - prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) - - flags = _bin_openflags - if _O_TMPFILE_WORKS: - try: - flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT - fd = _os.open(dir, flags2, 0o600) - except IsADirectoryError: - # Linux kernel older than 3.11 ignores the O_TMPFILE flag: - # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory - # with O_RDWR|O_DIRECTORY fails with IsADirectoryError, a - # directory cannot be open to write. Set flag to False to not - # try again. - _O_TMPFILE_WORKS = False - except OSError: - # The filesystem of the directory does not support O_TMPFILE. - # For example, OSError(95, 'Operation not supported'). - # - # On Linux kernel older than 3.11, trying to open a regular - # file (or a symbolic link to a regular file) with O_TMPFILE - # fails with NotADirectoryError, because O_TMPFILE is read as - # O_DIRECTORY. - pass - else: - try: - return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) - except: - _os.close(fd) - raise - # Fallback to _mkstemp_inner(). - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) - try: - _os.unlink(name) - return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) - except: - _os.close(fd) - raise - -class SpooledTemporaryFile: - """Temporary file wrapper, specialized to switch from BytesIO - or StringIO to a real file when it exceeds a certain size or - when a fileno is needed. - """ - _rolled = False - - def __init__(self, max_size=0, mode='w+b', buffering=-1, - encoding=None, newline=None, - suffix=None, prefix=None, dir=None): - if 'b' in mode: - self._file = _io.BytesIO() - else: - self._file = _io.TextIOWrapper(_io.BytesIO(), - encoding=encoding, newline=newline) - self._max_size = max_size - self._rolled = False - self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering, - 'suffix': suffix, 'prefix': prefix, - 'encoding': encoding, 'newline': newline, - 'dir': dir} - - def _check(self, file): - if self._rolled: return - max_size = self._max_size - if max_size and file.tell() > max_size: - self.rollover() - - def rollover(self): - if self._rolled: return - file = self._file - newfile = self._file = TemporaryFile(**self._TemporaryFileArgs) - del self._TemporaryFileArgs - - pos = file.tell() - if hasattr(newfile, 'buffer'): - newfile.buffer.write(file.detach().getvalue()) - else: - newfile.write(file.getvalue()) - newfile.seek(pos, 0) - - self._rolled = True - - # The method caching trick from NamedTemporaryFile - # won't work here, because _file may change from a - # BytesIO/StringIO instance to a real file. So we list - # all the methods directly. - - # Context management protocol - def __enter__(self): - if self._file.closed: - raise ValueError("Cannot enter context with closed file") - return self - - def __exit__(self, exc, value, tb): - self._file.close() - - # file protocol - def __iter__(self): - return self._file.__iter__() - - def close(self): - self._file.close() - - @property - def closed(self): - return self._file.closed - - @property - def encoding(self): - try: - return self._file.encoding - except AttributeError: - if 'b' in self._TemporaryFileArgs['mode']: - raise - return self._TemporaryFileArgs['encoding'] - - def fileno(self): - self.rollover() - return self._file.fileno() - - def flush(self): - self._file.flush() - - def isatty(self): - return self._file.isatty() - - @property - def mode(self): - try: - return self._file.mode - except AttributeError: - return self._TemporaryFileArgs['mode'] - - @property - def name(self): - try: - return self._file.name - except AttributeError: - return None - - @property - def newlines(self): - try: - return self._file.newlines - except AttributeError: - if 'b' in self._TemporaryFileArgs['mode']: - raise - return self._TemporaryFileArgs['newline'] - - def read(self, *args): - return self._file.read(*args) - - def readline(self, *args): - return self._file.readline(*args) - - def readlines(self, *args): - return self._file.readlines(*args) - - def seek(self, *args): - self._file.seek(*args) - - @property - def softspace(self): - return self._file.softspace - - def tell(self): - return self._file.tell() - - def truncate(self, size=None): - if size is None: - self._file.truncate() - else: - if size > self._max_size: - self.rollover() - self._file.truncate(size) - - def write(self, s): - file = self._file - rv = file.write(s) - self._check(file) - return rv - - def writelines(self, iterable): - file = self._file - rv = file.writelines(iterable) - self._check(file) - return rv - - -class TemporaryDirectory(object): - """Create and return a temporary directory. This has the same - behavior as mkdtemp but can be used as a context manager. For - example: - - with TemporaryDirectory() as tmpdir: - ... - - Upon exiting the context, the directory and everything contained - in it are removed. - """ - - def __init__(self, suffix=None, prefix=None, dir=None): - self.name = mkdtemp(suffix, prefix, dir) - self._finalizer = _weakref.finalize( - self, self._cleanup, self.name, - warn_message="Implicitly cleaning up {!r}".format(self)) - - @classmethod - def _cleanup(cls, name, warn_message): - _shutil.rmtree(name) - _warnings.warn(warn_message, ResourceWarning) - - def __repr__(self): - return "<{} {!r}>".format(self.__class__.__name__, self.name) - - def __enter__(self): - return self.name - - def __exit__(self, exc, value, tb): - self.cleanup() - - def cleanup(self): - if self._finalizer.detach(): - _shutil.rmtree(self.name) diff --git a/experiment/simulation/backend/venv/lib/python3.7/token.py b/experiment/simulation/backend/venv/lib/python3.7/token.py deleted file mode 100644 index ba13205..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/token.py +++ /dev/null @@ -1,160 +0,0 @@ -"""Token constants (from "token.h").""" - -__all__ = ['tok_name', 'ISTERMINAL', 'ISNONTERMINAL', 'ISEOF'] - -# This file is automatically generated; please don't muck it up! -# -# To update the symbols in this file, 'cd' to the top directory of -# the python source tree after building the interpreter and run: -# -# ./python Lib/token.py - -#--start constants-- -ENDMARKER = 0 -NAME = 1 -NUMBER = 2 -STRING = 3 -NEWLINE = 4 -INDENT = 5 -DEDENT = 6 -LPAR = 7 -RPAR = 8 -LSQB = 9 -RSQB = 10 -COLON = 11 -COMMA = 12 -SEMI = 13 -PLUS = 14 -MINUS = 15 -STAR = 16 -SLASH = 17 -VBAR = 18 -AMPER = 19 -LESS = 20 -GREATER = 21 -EQUAL = 22 -DOT = 23 -PERCENT = 24 -LBRACE = 25 -RBRACE = 26 -EQEQUAL = 27 -NOTEQUAL = 28 -LESSEQUAL = 29 -GREATEREQUAL = 30 -TILDE = 31 -CIRCUMFLEX = 32 -LEFTSHIFT = 33 -RIGHTSHIFT = 34 -DOUBLESTAR = 35 -PLUSEQUAL = 36 -MINEQUAL = 37 -STAREQUAL = 38 -SLASHEQUAL = 39 -PERCENTEQUAL = 40 -AMPEREQUAL = 41 -VBAREQUAL = 42 -CIRCUMFLEXEQUAL = 43 -LEFTSHIFTEQUAL = 44 -RIGHTSHIFTEQUAL = 45 -DOUBLESTAREQUAL = 46 -DOUBLESLASH = 47 -DOUBLESLASHEQUAL = 48 -AT = 49 -ATEQUAL = 50 -RARROW = 51 -ELLIPSIS = 52 -# Don't forget to update the table _PyParser_TokenNames in tokenizer.c! -OP = 53 -ERRORTOKEN = 54 -# These aren't used by the C tokenizer but are needed for tokenize.py -COMMENT = 55 -NL = 56 -ENCODING = 57 -N_TOKENS = 58 -# Special definitions for cooperation with parser -NT_OFFSET = 256 -#--end constants-- - -tok_name = {value: name - for name, value in globals().items() - if isinstance(value, int) and not name.startswith('_')} -__all__.extend(tok_name.values()) - -def ISTERMINAL(x): - return x < NT_OFFSET - -def ISNONTERMINAL(x): - return x >= NT_OFFSET - -def ISEOF(x): - return x == ENDMARKER - - -def _main(): - import re - import sys - args = sys.argv[1:] - inFileName = args and args[0] or "Include/token.h" - outFileName = "Lib/token.py" - if len(args) > 1: - outFileName = args[1] - try: - fp = open(inFileName) - except OSError as err: - sys.stdout.write("I/O error: %s\n" % str(err)) - sys.exit(1) - with fp: - lines = fp.read().split("\n") - prog = re.compile( - r"#define[ \t][ \t]*([A-Z0-9][A-Z0-9_]*)[ \t][ \t]*([0-9][0-9]*)", - re.IGNORECASE) - comment_regex = re.compile( - r"^\s*/\*\s*(.+?)\s*\*/\s*$", - re.IGNORECASE) - - tokens = {} - prev_val = None - for line in lines: - match = prog.match(line) - if match: - name, val = match.group(1, 2) - val = int(val) - tokens[val] = {'token': name} # reverse so we can sort them... - prev_val = val - else: - comment_match = comment_regex.match(line) - if comment_match and prev_val is not None: - comment = comment_match.group(1) - tokens[prev_val]['comment'] = comment - keys = sorted(tokens.keys()) - # load the output skeleton from the target: - try: - fp = open(outFileName) - except OSError as err: - sys.stderr.write("I/O error: %s\n" % str(err)) - sys.exit(2) - with fp: - format = fp.read().split("\n") - try: - start = format.index("#--start constants--") + 1 - end = format.index("#--end constants--") - except ValueError: - sys.stderr.write("target does not contain format markers") - sys.exit(3) - lines = [] - for key in keys: - lines.append("%s = %d" % (tokens[key]["token"], key)) - if "comment" in tokens[key]: - lines.append("# %s" % tokens[key]["comment"]) - format[start:end] = lines - try: - fp = open(outFileName, 'w') - except OSError as err: - sys.stderr.write("I/O error: %s\n" % str(err)) - sys.exit(4) - with fp: - fp.write("\n".join(format)) - - -if __name__ == "__main__": - _main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/tokenize.py b/experiment/simulation/backend/venv/lib/python3.7/tokenize.py deleted file mode 100644 index 8305bf9..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/tokenize.py +++ /dev/null @@ -1,736 +0,0 @@ -"""Tokenization help for Python programs. - -tokenize(readline) is a generator that breaks a stream of bytes into -Python tokens. It decodes the bytes according to PEP-0263 for -determining source file encoding. - -It accepts a readline-like method which is called repeatedly to get the -next line of input (or b"" for EOF). It generates 5-tuples with these -members: - - the token type (see token.py) - the token (a string) - the starting (row, column) indices of the token (a 2-tuple of ints) - the ending (row, column) indices of the token (a 2-tuple of ints) - the original line (string) - -It is designed to match the working of the Python tokenizer exactly, except -that it produces COMMENT tokens for comments and gives type OP for all -operators. Additionally, all token lists start with an ENCODING token -which tells you which encoding was used to decode the bytes stream. -""" - -__author__ = 'Ka-Ping Yee ' -__credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, ' - 'Skip Montanaro, Raymond Hettinger, Trent Nelson, ' - 'Michael Foord') -from builtins import open as _builtin_open -from codecs import lookup, BOM_UTF8 -import collections -from io import TextIOWrapper -from itertools import chain -import itertools as _itertools -import re -import sys -from token import * - -cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII) -blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) - -import token -__all__ = token.__all__ + ["tokenize", "detect_encoding", - "untokenize", "TokenInfo"] -del token - -EXACT_TOKEN_TYPES = { - '(': LPAR, - ')': RPAR, - '[': LSQB, - ']': RSQB, - ':': COLON, - ',': COMMA, - ';': SEMI, - '+': PLUS, - '-': MINUS, - '*': STAR, - '/': SLASH, - '|': VBAR, - '&': AMPER, - '<': LESS, - '>': GREATER, - '=': EQUAL, - '.': DOT, - '%': PERCENT, - '{': LBRACE, - '}': RBRACE, - '==': EQEQUAL, - '!=': NOTEQUAL, - '<=': LESSEQUAL, - '>=': GREATEREQUAL, - '~': TILDE, - '^': CIRCUMFLEX, - '<<': LEFTSHIFT, - '>>': RIGHTSHIFT, - '**': DOUBLESTAR, - '+=': PLUSEQUAL, - '-=': MINEQUAL, - '*=': STAREQUAL, - '/=': SLASHEQUAL, - '%=': PERCENTEQUAL, - '&=': AMPEREQUAL, - '|=': VBAREQUAL, - '^=': CIRCUMFLEXEQUAL, - '<<=': LEFTSHIFTEQUAL, - '>>=': RIGHTSHIFTEQUAL, - '**=': DOUBLESTAREQUAL, - '//': DOUBLESLASH, - '//=': DOUBLESLASHEQUAL, - '...': ELLIPSIS, - '->': RARROW, - '@': AT, - '@=': ATEQUAL, -} - -class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')): - def __repr__(self): - annotated_type = '%d (%s)' % (self.type, tok_name[self.type]) - return ('TokenInfo(type=%s, string=%r, start=%r, end=%r, line=%r)' % - self._replace(type=annotated_type)) - - @property - def exact_type(self): - if self.type == OP and self.string in EXACT_TOKEN_TYPES: - return EXACT_TOKEN_TYPES[self.string] - else: - return self.type - -def group(*choices): return '(' + '|'.join(choices) + ')' -def any(*choices): return group(*choices) + '*' -def maybe(*choices): return group(*choices) + '?' - -# Note: we use unicode matching for names ("\w") but ascii matching for -# number literals. -Whitespace = r'[ \f\t]*' -Comment = r'#[^\r\n]*' -Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment) -Name = r'\w+' - -Hexnumber = r'0[xX](?:_?[0-9a-fA-F])+' -Binnumber = r'0[bB](?:_?[01])+' -Octnumber = r'0[oO](?:_?[0-7])+' -Decnumber = r'(?:0(?:_?0)*|[1-9](?:_?[0-9])*)' -Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber) -Exponent = r'[eE][-+]?[0-9](?:_?[0-9])*' -Pointfloat = group(r'[0-9](?:_?[0-9])*\.(?:[0-9](?:_?[0-9])*)?', - r'\.[0-9](?:_?[0-9])*') + maybe(Exponent) -Expfloat = r'[0-9](?:_?[0-9])*' + Exponent -Floatnumber = group(Pointfloat, Expfloat) -Imagnumber = group(r'[0-9](?:_?[0-9])*[jJ]', Floatnumber + r'[jJ]') -Number = group(Imagnumber, Floatnumber, Intnumber) - -# Return the empty string, plus all of the valid string prefixes. -def _all_string_prefixes(): - # The valid string prefixes. Only contain the lower case versions, - # and don't contain any permutations (include 'fr', but not - # 'rf'). The various permutations will be generated. - _valid_string_prefixes = ['b', 'r', 'u', 'f', 'br', 'fr'] - # if we add binary f-strings, add: ['fb', 'fbr'] - result = {''} - for prefix in _valid_string_prefixes: - for t in _itertools.permutations(prefix): - # create a list with upper and lower versions of each - # character - for u in _itertools.product(*[(c, c.upper()) for c in t]): - result.add(''.join(u)) - return result - -def _compile(expr): - return re.compile(expr, re.UNICODE) - -# Note that since _all_string_prefixes includes the empty string, -# StringPrefix can be the empty string (making it optional). -StringPrefix = group(*_all_string_prefixes()) - -# Tail end of ' string. -Single = r"[^'\\]*(?:\\.[^'\\]*)*'" -# Tail end of " string. -Double = r'[^"\\]*(?:\\.[^"\\]*)*"' -# Tail end of ''' string. -Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''" -# Tail end of """ string. -Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""' -Triple = group(StringPrefix + "'''", StringPrefix + '"""') -# Single-line ' or " string. -String = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'", - StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"') - -# Because of leftmost-then-longest match semantics, be sure to put the -# longest operators first (e.g., if = came before ==, == would get -# recognized as two instances of =). -Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=", - r"//=?", r"->", - r"[+\-*/%&@|^=<>]=?", - r"~") - -Bracket = '[][(){}]' -Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]') -Funny = group(Operator, Bracket, Special) - -PlainToken = group(Number, Funny, String, Name) -Token = Ignore + PlainToken - -# First (or only) line of ' or " string. -ContStr = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" + - group("'", r'\\\r?\n'), - StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' + - group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) -PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) - -# For a given string prefix plus quotes, endpats maps it to a regex -# to match the remainder of that string. _prefix can be empty, for -# a normal single or triple quoted string (with no prefix). -endpats = {} -for _prefix in _all_string_prefixes(): - endpats[_prefix + "'"] = Single - endpats[_prefix + '"'] = Double - endpats[_prefix + "'''"] = Single3 - endpats[_prefix + '"""'] = Double3 - -# A set of all of the single and triple quoted string prefixes, -# including the opening quotes. -single_quoted = set() -triple_quoted = set() -for t in _all_string_prefixes(): - for u in (t + '"', t + "'"): - single_quoted.add(u) - for u in (t + '"""', t + "'''"): - triple_quoted.add(u) - -tabsize = 8 - -class TokenError(Exception): pass - -class StopTokenizing(Exception): pass - - -class Untokenizer: - - def __init__(self): - self.tokens = [] - self.prev_row = 1 - self.prev_col = 0 - self.encoding = None - - def add_whitespace(self, start): - row, col = start - if row < self.prev_row or row == self.prev_row and col < self.prev_col: - raise ValueError("start ({},{}) precedes previous end ({},{})" - .format(row, col, self.prev_row, self.prev_col)) - row_offset = row - self.prev_row - if row_offset: - self.tokens.append("\\\n" * row_offset) - self.prev_col = 0 - col_offset = col - self.prev_col - if col_offset: - self.tokens.append(" " * col_offset) - - def untokenize(self, iterable): - it = iter(iterable) - indents = [] - startline = False - for t in it: - if len(t) == 2: - self.compat(t, it) - break - tok_type, token, start, end, line = t - if tok_type == ENCODING: - self.encoding = token - continue - if tok_type == ENDMARKER: - break - if tok_type == INDENT: - indents.append(token) - continue - elif tok_type == DEDENT: - indents.pop() - self.prev_row, self.prev_col = end - continue - elif tok_type in (NEWLINE, NL): - startline = True - elif startline and indents: - indent = indents[-1] - if start[1] >= len(indent): - self.tokens.append(indent) - self.prev_col = len(indent) - startline = False - self.add_whitespace(start) - self.tokens.append(token) - self.prev_row, self.prev_col = end - if tok_type in (NEWLINE, NL): - self.prev_row += 1 - self.prev_col = 0 - return "".join(self.tokens) - - def compat(self, token, iterable): - indents = [] - toks_append = self.tokens.append - startline = token[0] in (NEWLINE, NL) - prevstring = False - - for tok in chain([token], iterable): - toknum, tokval = tok[:2] - if toknum == ENCODING: - self.encoding = tokval - continue - - if toknum in (NAME, NUMBER): - tokval += ' ' - - # Insert a space between two consecutive strings - if toknum == STRING: - if prevstring: - tokval = ' ' + tokval - prevstring = True - else: - prevstring = False - - if toknum == INDENT: - indents.append(tokval) - continue - elif toknum == DEDENT: - indents.pop() - continue - elif toknum in (NEWLINE, NL): - startline = True - elif startline and indents: - toks_append(indents[-1]) - startline = False - toks_append(tokval) - - -def untokenize(iterable): - """Transform tokens back into Python source code. - It returns a bytes object, encoded using the ENCODING - token, which is the first token sequence output by tokenize. - - Each element returned by the iterable must be a token sequence - with at least two elements, a token number and token value. If - only two tokens are passed, the resulting output is poor. - - Round-trip invariant for full input: - Untokenized source will match input source exactly - - Round-trip invariant for limited input: - # Output bytes will tokenize back to the input - t1 = [tok[:2] for tok in tokenize(f.readline)] - newcode = untokenize(t1) - readline = BytesIO(newcode).readline - t2 = [tok[:2] for tok in tokenize(readline)] - assert t1 == t2 - """ - ut = Untokenizer() - out = ut.untokenize(iterable) - if ut.encoding is not None: - out = out.encode(ut.encoding) - return out - - -def _get_normal_name(orig_enc): - """Imitates get_normal_name in tokenizer.c.""" - # Only care about the first 12 characters. - enc = orig_enc[:12].lower().replace("_", "-") - if enc == "utf-8" or enc.startswith("utf-8-"): - return "utf-8" - if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ - enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): - return "iso-8859-1" - return orig_enc - -def detect_encoding(readline): - """ - The detect_encoding() function is used to detect the encoding that should - be used to decode a Python source file. It requires one argument, readline, - in the same way as the tokenize() generator. - - It will call readline a maximum of twice, and return the encoding used - (as a string) and a list of any lines (left as bytes) it has read in. - - It detects the encoding from the presence of a utf-8 bom or an encoding - cookie as specified in pep-0263. If both a bom and a cookie are present, - but disagree, a SyntaxError will be raised. If the encoding cookie is an - invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, - 'utf-8-sig' is returned. - - If no encoding is specified, then the default of 'utf-8' will be returned. - """ - try: - filename = readline.__self__.name - except AttributeError: - filename = None - bom_found = False - encoding = None - default = 'utf-8' - def read_or_stop(): - try: - return readline() - except StopIteration: - return b'' - - def find_cookie(line): - try: - # Decode as UTF-8. Either the line is an encoding declaration, - # in which case it should be pure ASCII, or it must be UTF-8 - # per default encoding. - line_string = line.decode('utf-8') - except UnicodeDecodeError: - msg = "invalid or missing encoding declaration" - if filename is not None: - msg = '{} for {!r}'.format(msg, filename) - raise SyntaxError(msg) - - match = cookie_re.match(line_string) - if not match: - return None - encoding = _get_normal_name(match.group(1)) - try: - codec = lookup(encoding) - except LookupError: - # This behaviour mimics the Python interpreter - if filename is None: - msg = "unknown encoding: " + encoding - else: - msg = "unknown encoding for {!r}: {}".format(filename, - encoding) - raise SyntaxError(msg) - - if bom_found: - if encoding != 'utf-8': - # This behaviour mimics the Python interpreter - if filename is None: - msg = 'encoding problem: utf-8' - else: - msg = 'encoding problem for {!r}: utf-8'.format(filename) - raise SyntaxError(msg) - encoding += '-sig' - return encoding - - first = read_or_stop() - if first.startswith(BOM_UTF8): - bom_found = True - first = first[3:] - default = 'utf-8-sig' - if not first: - return default, [] - - encoding = find_cookie(first) - if encoding: - return encoding, [first] - if not blank_re.match(first): - return default, [first] - - second = read_or_stop() - if not second: - return default, [first] - - encoding = find_cookie(second) - if encoding: - return encoding, [first, second] - - return default, [first, second] - - -def open(filename): - """Open a file in read only mode using the encoding detected by - detect_encoding(). - """ - buffer = _builtin_open(filename, 'rb') - try: - encoding, lines = detect_encoding(buffer.readline) - buffer.seek(0) - text = TextIOWrapper(buffer, encoding, line_buffering=True) - text.mode = 'r' - return text - except: - buffer.close() - raise - - -def tokenize(readline): - """ - The tokenize() generator requires one argument, readline, which - must be a callable object which provides the same interface as the - readline() method of built-in file objects. Each call to the function - should return one line of input as bytes. Alternatively, readline - can be a callable function terminating with StopIteration: - readline = open(myfile, 'rb').__next__ # Example of alternate readline - - The generator produces 5-tuples with these members: the token type; the - token string; a 2-tuple (srow, scol) of ints specifying the row and - column where the token begins in the source; a 2-tuple (erow, ecol) of - ints specifying the row and column where the token ends in the source; - and the line on which the token was found. The line passed is the - logical line; continuation lines are included. - - The first token sequence will always be an ENCODING token - which tells you which encoding was used to decode the bytes stream. - """ - # This import is here to avoid problems when the itertools module is not - # built yet and tokenize is imported. - from itertools import chain, repeat - encoding, consumed = detect_encoding(readline) - rl_gen = iter(readline, b"") - empty = repeat(b"") - return _tokenize(chain(consumed, rl_gen, empty).__next__, encoding) - - -def _tokenize(readline, encoding): - lnum = parenlev = continued = 0 - numchars = '0123456789' - contstr, needcont = '', 0 - contline = None - indents = [0] - - if encoding is not None: - if encoding == "utf-8-sig": - # BOM will already have been stripped. - encoding = "utf-8" - yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '') - last_line = b'' - line = b'' - while True: # loop over lines in stream - try: - # We capture the value of the line variable here because - # readline uses the empty string '' to signal end of input, - # hence `line` itself will always be overwritten at the end - # of this loop. - last_line = line - line = readline() - except StopIteration: - line = b'' - - if encoding is not None: - line = line.decode(encoding) - lnum += 1 - pos, max = 0, len(line) - - if contstr: # continued string - if not line: - raise TokenError("EOF in multi-line string", strstart) - endmatch = endprog.match(line) - if endmatch: - pos = end = endmatch.end(0) - yield TokenInfo(STRING, contstr + line[:end], - strstart, (lnum, end), contline + line) - contstr, needcont = '', 0 - contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': - yield TokenInfo(ERRORTOKEN, contstr + line, - strstart, (lnum, len(line)), contline) - contstr = '' - contline = None - continue - else: - contstr = contstr + line - contline = contline + line - continue - - elif parenlev == 0 and not continued: # new statement - if not line: break - column = 0 - while pos < max: # measure leading whitespace - if line[pos] == ' ': - column += 1 - elif line[pos] == '\t': - column = (column//tabsize + 1)*tabsize - elif line[pos] == '\f': - column = 0 - else: - break - pos += 1 - if pos == max: - break - - if line[pos] in '#\r\n': # skip comments or blank lines - if line[pos] == '#': - comment_token = line[pos:].rstrip('\r\n') - yield TokenInfo(COMMENT, comment_token, - (lnum, pos), (lnum, pos + len(comment_token)), line) - pos += len(comment_token) - - yield TokenInfo(NL, line[pos:], - (lnum, pos), (lnum, len(line)), line) - continue - - if column > indents[-1]: # count indents or dedents - indents.append(column) - yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line) - while column < indents[-1]: - if column not in indents: - raise IndentationError( - "unindent does not match any outer indentation level", - ("", lnum, pos, line)) - indents = indents[:-1] - - yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) - - else: # continued statement - if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0)) - continued = 0 - - while pos < max: - pseudomatch = _compile(PseudoToken).match(line, pos) - if pseudomatch: # scan for tokens - start, end = pseudomatch.span(1) - spos, epos, pos = (lnum, start), (lnum, end), end - if start == end: - continue - token, initial = line[start:end], line[start] - - if (initial in numchars or # ordinary number - (initial == '.' and token != '.' and token != '...')): - yield TokenInfo(NUMBER, token, spos, epos, line) - elif initial in '\r\n': - if parenlev > 0: - yield TokenInfo(NL, token, spos, epos, line) - else: - yield TokenInfo(NEWLINE, token, spos, epos, line) - - elif initial == '#': - assert not token.endswith("\n") - yield TokenInfo(COMMENT, token, spos, epos, line) - - elif token in triple_quoted: - endprog = _compile(endpats[token]) - endmatch = endprog.match(line, pos) - if endmatch: # all on one line - pos = endmatch.end(0) - token = line[start:pos] - yield TokenInfo(STRING, token, spos, (lnum, pos), line) - else: - strstart = (lnum, start) # multiple lines - contstr = line[start:] - contline = line - break - - # Check up to the first 3 chars of the token to see if - # they're in the single_quoted set. If so, they start - # a string. - # We're using the first 3, because we're looking for - # "rb'" (for example) at the start of the token. If - # we switch to longer prefixes, this needs to be - # adjusted. - # Note that initial == token[:1]. - # Also note that single quote checking must come after - # triple quote checking (above). - elif (initial in single_quoted or - token[:2] in single_quoted or - token[:3] in single_quoted): - if token[-1] == '\n': # continued string - strstart = (lnum, start) - # Again, using the first 3 chars of the - # token. This is looking for the matching end - # regex for the correct type of quote - # character. So it's really looking for - # endpats["'"] or endpats['"'], by trying to - # skip string prefix characters, if any. - endprog = _compile(endpats.get(initial) or - endpats.get(token[1]) or - endpats.get(token[2])) - contstr, needcont = line[start:], 1 - contline = line - break - else: # ordinary string - yield TokenInfo(STRING, token, spos, epos, line) - - elif initial.isidentifier(): # ordinary name - yield TokenInfo(NAME, token, spos, epos, line) - elif initial == '\\': # continued stmt - continued = 1 - else: - if initial in '([{': - parenlev += 1 - elif initial in ')]}': - parenlev -= 1 - yield TokenInfo(OP, token, spos, epos, line) - else: - yield TokenInfo(ERRORTOKEN, line[pos], - (lnum, pos), (lnum, pos+1), line) - pos += 1 - - # Add an implicit NEWLINE if the input doesn't end in one - if last_line and last_line[-1] not in '\r\n': - yield TokenInfo(NEWLINE, '', (lnum - 1, len(last_line)), (lnum - 1, len(last_line) + 1), '') - for indent in indents[1:]: # pop remaining indent levels - yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '') - yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '') - - -# An undocumented, backwards compatible, API for all the places in the standard -# library that expect to be able to use tokenize with strings -def generate_tokens(readline): - return _tokenize(readline, None) - -def main(): - import argparse - - # Helper error handling routines - def perror(message): - print(message, file=sys.stderr) - - def error(message, filename=None, location=None): - if location: - args = (filename,) + location + (message,) - perror("%s:%d:%d: error: %s" % args) - elif filename: - perror("%s: error: %s" % (filename, message)) - else: - perror("error: %s" % message) - sys.exit(1) - - # Parse the arguments and options - parser = argparse.ArgumentParser(prog='python -m tokenize') - parser.add_argument(dest='filename', nargs='?', - metavar='filename.py', - help='the file to tokenize; defaults to stdin') - parser.add_argument('-e', '--exact', dest='exact', action='store_true', - help='display token names using the exact type') - args = parser.parse_args() - - try: - # Tokenize the input - if args.filename: - filename = args.filename - with _builtin_open(filename, 'rb') as f: - tokens = list(tokenize(f.readline)) - else: - filename = "" - tokens = _tokenize(sys.stdin.readline, None) - - # Output the tokenization - for token in tokens: - token_type = token.type - if args.exact: - token_type = token.exact_type - token_range = "%d,%d-%d,%d:" % (token.start + token.end) - print("%-20s%-15s%-15r" % - (token_range, tok_name[token_type], token.string)) - except IndentationError as err: - line, column = err.args[1][1:3] - error(err.args[0], filename, (line, column)) - except TokenError as err: - line, column = err.args[1] - error(err.args[0], filename, (line, column)) - except SyntaxError as err: - error(err, filename) - except OSError as err: - error(err) - except KeyboardInterrupt: - print("interrupted\n") - except Exception as err: - perror("unexpected error: %s" % err) - raise - -if __name__ == "__main__": - main() diff --git a/experiment/simulation/backend/venv/lib/python3.7/types.py b/experiment/simulation/backend/venv/lib/python3.7/types.py deleted file mode 100644 index 2e0513c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/types.py +++ /dev/null @@ -1,295 +0,0 @@ -""" -Define names for built-in types that aren't directly accessible as a builtin. -""" -import sys - -# Iterators in Python aren't a matter of type but of protocol. A large -# and changing number of builtin types implement *some* flavor of -# iterator. Don't check the type! Use hasattr to check for both -# "__iter__" and "__next__" attributes instead. - -def _f(): pass -FunctionType = type(_f) -LambdaType = type(lambda: None) # Same as FunctionType -CodeType = type(_f.__code__) -MappingProxyType = type(type.__dict__) -SimpleNamespace = type(sys.implementation) - -def _g(): - yield 1 -GeneratorType = type(_g()) - -async def _c(): pass -_c = _c() -CoroutineType = type(_c) -_c.close() # Prevent ResourceWarning - -async def _ag(): - yield -_ag = _ag() -AsyncGeneratorType = type(_ag) - -class _C: - def _m(self): pass -MethodType = type(_C()._m) - -BuiltinFunctionType = type(len) -BuiltinMethodType = type([].append) # Same as BuiltinFunctionType - -WrapperDescriptorType = type(object.__init__) -MethodWrapperType = type(object().__str__) -MethodDescriptorType = type(str.join) -ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) - -ModuleType = type(sys) - -try: - raise TypeError -except TypeError: - tb = sys.exc_info()[2] - TracebackType = type(tb) - FrameType = type(tb.tb_frame) - tb = None; del tb - -# For Jython, the following two types are identical -GetSetDescriptorType = type(FunctionType.__code__) -MemberDescriptorType = type(FunctionType.__globals__) - -del sys, _f, _g, _C, _c, _ag # Not for export - - -# Provide a PEP 3115 compliant mechanism for class creation -def new_class(name, bases=(), kwds=None, exec_body=None): - """Create a class object dynamically using the appropriate metaclass.""" - resolved_bases = resolve_bases(bases) - meta, ns, kwds = prepare_class(name, resolved_bases, kwds) - if exec_body is not None: - exec_body(ns) - if resolved_bases is not bases: - ns['__orig_bases__'] = bases - return meta(name, resolved_bases, ns, **kwds) - -def resolve_bases(bases): - """Resolve MRO entries dynamically as specified by PEP 560.""" - new_bases = list(bases) - updated = False - shift = 0 - for i, base in enumerate(bases): - if isinstance(base, type): - continue - if not hasattr(base, "__mro_entries__"): - continue - new_base = base.__mro_entries__(bases) - updated = True - if not isinstance(new_base, tuple): - raise TypeError("__mro_entries__ must return a tuple") - else: - new_bases[i+shift:i+shift+1] = new_base - shift += len(new_base) - 1 - if not updated: - return bases - return tuple(new_bases) - -def prepare_class(name, bases=(), kwds=None): - """Call the __prepare__ method of the appropriate metaclass. - - Returns (metaclass, namespace, kwds) as a 3-tuple - - *metaclass* is the appropriate metaclass - *namespace* is the prepared class namespace - *kwds* is an updated copy of the passed in kwds argument with any - 'metaclass' entry removed. If no kwds argument is passed in, this will - be an empty dict. - """ - if kwds is None: - kwds = {} - else: - kwds = dict(kwds) # Don't alter the provided mapping - if 'metaclass' in kwds: - meta = kwds.pop('metaclass') - else: - if bases: - meta = type(bases[0]) - else: - meta = type - if isinstance(meta, type): - # when meta is a type, we first determine the most-derived metaclass - # instead of invoking the initial candidate directly - meta = _calculate_meta(meta, bases) - if hasattr(meta, '__prepare__'): - ns = meta.__prepare__(name, bases, **kwds) - else: - ns = {} - return meta, ns, kwds - -def _calculate_meta(meta, bases): - """Calculate the most derived metaclass.""" - winner = meta - for base in bases: - base_meta = type(base) - if issubclass(winner, base_meta): - continue - if issubclass(base_meta, winner): - winner = base_meta - continue - # else: - raise TypeError("metaclass conflict: " - "the metaclass of a derived class " - "must be a (non-strict) subclass " - "of the metaclasses of all its bases") - return winner - -class DynamicClassAttribute: - """Route attribute access on a class to __getattr__. - - This is a descriptor, used to define attributes that act differently when - accessed through an instance and through a class. Instance access remains - normal, but access to an attribute through a class will be routed to the - class's __getattr__ method; this is done by raising AttributeError. - - This allows one to have properties active on an instance, and have virtual - attributes on the class with the same name (see Enum for an example). - - """ - def __init__(self, fget=None, fset=None, fdel=None, doc=None): - self.fget = fget - self.fset = fset - self.fdel = fdel - # next two lines make DynamicClassAttribute act the same as property - self.__doc__ = doc or fget.__doc__ - self.overwrite_doc = doc is None - # support for abstract methods - self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False)) - - def __get__(self, instance, ownerclass=None): - if instance is None: - if self.__isabstractmethod__: - return self - raise AttributeError() - elif self.fget is None: - raise AttributeError("unreadable attribute") - return self.fget(instance) - - def __set__(self, instance, value): - if self.fset is None: - raise AttributeError("can't set attribute") - self.fset(instance, value) - - def __delete__(self, instance): - if self.fdel is None: - raise AttributeError("can't delete attribute") - self.fdel(instance) - - def getter(self, fget): - fdoc = fget.__doc__ if self.overwrite_doc else None - result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__) - result.overwrite_doc = self.overwrite_doc - return result - - def setter(self, fset): - result = type(self)(self.fget, fset, self.fdel, self.__doc__) - result.overwrite_doc = self.overwrite_doc - return result - - def deleter(self, fdel): - result = type(self)(self.fget, self.fset, fdel, self.__doc__) - result.overwrite_doc = self.overwrite_doc - return result - - -class _GeneratorWrapper: - # TODO: Implement this in C. - def __init__(self, gen): - self.__wrapped = gen - self.__isgen = gen.__class__ is GeneratorType - self.__name__ = getattr(gen, '__name__', None) - self.__qualname__ = getattr(gen, '__qualname__', None) - def send(self, val): - return self.__wrapped.send(val) - def throw(self, tp, *rest): - return self.__wrapped.throw(tp, *rest) - def close(self): - return self.__wrapped.close() - @property - def gi_code(self): - return self.__wrapped.gi_code - @property - def gi_frame(self): - return self.__wrapped.gi_frame - @property - def gi_running(self): - return self.__wrapped.gi_running - @property - def gi_yieldfrom(self): - return self.__wrapped.gi_yieldfrom - cr_code = gi_code - cr_frame = gi_frame - cr_running = gi_running - cr_await = gi_yieldfrom - def __next__(self): - return next(self.__wrapped) - def __iter__(self): - if self.__isgen: - return self.__wrapped - return self - __await__ = __iter__ - -def coroutine(func): - """Convert regular generator function to a coroutine.""" - - if not callable(func): - raise TypeError('types.coroutine() expects a callable') - - if (func.__class__ is FunctionType and - getattr(func, '__code__', None).__class__ is CodeType): - - co_flags = func.__code__.co_flags - - # Check if 'func' is a coroutine function. - # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE) - if co_flags & 0x180: - return func - - # Check if 'func' is a generator function. - # (0x20 == CO_GENERATOR) - if co_flags & 0x20: - # TODO: Implement this in C. - co = func.__code__ - func.__code__ = CodeType( - co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, - co.co_stacksize, - co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE - co.co_code, - co.co_consts, co.co_names, co.co_varnames, co.co_filename, - co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, - co.co_cellvars) - return func - - # The following code is primarily to support functions that - # return generator-like objects (for instance generators - # compiled with Cython). - - # Delay functools and _collections_abc import for speeding up types import. - import functools - import _collections_abc - @functools.wraps(func) - def wrapped(*args, **kwargs): - coro = func(*args, **kwargs) - if (coro.__class__ is CoroutineType or - coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100): - # 'coro' is a native coroutine object or an iterable coroutine - return coro - if (isinstance(coro, _collections_abc.Generator) and - not isinstance(coro, _collections_abc.Coroutine)): - # 'coro' is either a pure Python generator iterator, or it - # implements collections.abc.Generator (and does not implement - # collections.abc.Coroutine). - return _GeneratorWrapper(coro) - # 'coro' is either an instance of collections.abc.Coroutine or - # some other object -- pass it through. - return coro - - return wrapped - - -__all__ = [n for n in globals() if n[:1] != '_'] diff --git a/experiment/simulation/backend/venv/lib/python3.7/warnings.py b/experiment/simulation/backend/venv/lib/python3.7/warnings.py deleted file mode 100644 index 3e1715c..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/warnings.py +++ /dev/null @@ -1,561 +0,0 @@ -"""Python part of the warnings subsystem.""" - -import sys - - -__all__ = ["warn", "warn_explicit", "showwarning", - "formatwarning", "filterwarnings", "simplefilter", - "resetwarnings", "catch_warnings"] - -def showwarning(message, category, filename, lineno, file=None, line=None): - """Hook to write a warning to a file; replace if you like.""" - msg = WarningMessage(message, category, filename, lineno, file, line) - _showwarnmsg_impl(msg) - -def formatwarning(message, category, filename, lineno, line=None): - """Function to format a warning the standard way.""" - msg = WarningMessage(message, category, filename, lineno, None, line) - return _formatwarnmsg_impl(msg) - -def _showwarnmsg_impl(msg): - file = msg.file - if file is None: - file = sys.stderr - if file is None: - # sys.stderr is None when run with pythonw.exe: - # warnings get lost - return - text = _formatwarnmsg(msg) - try: - file.write(text) - except OSError: - # the file (probably stderr) is invalid - this warning gets lost. - pass - -def _formatwarnmsg_impl(msg): - category = msg.category.__name__ - s = f"{msg.filename}:{msg.lineno}: {category}: {msg.message}\n" - - if msg.line is None: - try: - import linecache - line = linecache.getline(msg.filename, msg.lineno) - except Exception: - # When a warning is logged during Python shutdown, linecache - # and the import machinery don't work anymore - line = None - linecache = None - else: - line = msg.line - if line: - line = line.strip() - s += " %s\n" % line - - if msg.source is not None: - try: - import tracemalloc - # Logging a warning should not raise a new exception: - # catch Exception, not only ImportError and RecursionError. - except Exception: - # don't suggest to enable tracemalloc if it's not available - tracing = True - tb = None - else: - tracing = tracemalloc.is_tracing() - try: - tb = tracemalloc.get_object_traceback(msg.source) - except Exception: - # When a warning is logged during Python shutdown, tracemalloc - # and the import machinery don't work anymore - tb = None - - if tb is not None: - s += 'Object allocated at (most recent call last):\n' - for frame in tb: - s += (' File "%s", lineno %s\n' - % (frame.filename, frame.lineno)) - - try: - if linecache is not None: - line = linecache.getline(frame.filename, frame.lineno) - else: - line = None - except Exception: - line = None - if line: - line = line.strip() - s += ' %s\n' % line - elif not tracing: - s += (f'{category}: Enable tracemalloc to get the object ' - f'allocation traceback\n') - return s - -# Keep a reference to check if the function was replaced -_showwarning_orig = showwarning - -def _showwarnmsg(msg): - """Hook to write a warning to a file; replace if you like.""" - try: - sw = showwarning - except NameError: - pass - else: - if sw is not _showwarning_orig: - # warnings.showwarning() was replaced - if not callable(sw): - raise TypeError("warnings.showwarning() must be set to a " - "function or method") - - sw(msg.message, msg.category, msg.filename, msg.lineno, - msg.file, msg.line) - return - _showwarnmsg_impl(msg) - -# Keep a reference to check if the function was replaced -_formatwarning_orig = formatwarning - -def _formatwarnmsg(msg): - """Function to format a warning the standard way.""" - try: - fw = formatwarning - except NameError: - pass - else: - if fw is not _formatwarning_orig: - # warnings.formatwarning() was replaced - return fw(msg.message, msg.category, - msg.filename, msg.lineno, msg.line) - return _formatwarnmsg_impl(msg) - -def filterwarnings(action, message="", category=Warning, module="", lineno=0, - append=False): - """Insert an entry into the list of warnings filters (at the front). - - 'action' -- one of "error", "ignore", "always", "default", "module", - or "once" - 'message' -- a regex that the warning message must match - 'category' -- a class that the warning must be a subclass of - 'module' -- a regex that the module name must match - 'lineno' -- an integer line number, 0 matches all warnings - 'append' -- if true, append to the list of filters - """ - assert action in ("error", "ignore", "always", "default", "module", - "once"), "invalid action: %r" % (action,) - assert isinstance(message, str), "message must be a string" - assert isinstance(category, type), "category must be a class" - assert issubclass(category, Warning), "category must be a Warning subclass" - assert isinstance(module, str), "module must be a string" - assert isinstance(lineno, int) and lineno >= 0, \ - "lineno must be an int >= 0" - - if message or module: - import re - - if message: - message = re.compile(message, re.I) - else: - message = None - if module: - module = re.compile(module) - else: - module = None - - _add_filter(action, message, category, module, lineno, append=append) - -def simplefilter(action, category=Warning, lineno=0, append=False): - """Insert a simple entry into the list of warnings filters (at the front). - - A simple filter matches all modules and messages. - 'action' -- one of "error", "ignore", "always", "default", "module", - or "once" - 'category' -- a class that the warning must be a subclass of - 'lineno' -- an integer line number, 0 matches all warnings - 'append' -- if true, append to the list of filters - """ - assert action in ("error", "ignore", "always", "default", "module", - "once"), "invalid action: %r" % (action,) - assert isinstance(lineno, int) and lineno >= 0, \ - "lineno must be an int >= 0" - _add_filter(action, None, category, None, lineno, append=append) - -def _add_filter(*item, append): - # Remove possible duplicate filters, so new one will be placed - # in correct place. If append=True and duplicate exists, do nothing. - if not append: - try: - filters.remove(item) - except ValueError: - pass - filters.insert(0, item) - else: - if item not in filters: - filters.append(item) - _filters_mutated() - -def resetwarnings(): - """Clear the list of warning filters, so that no filters are active.""" - filters[:] = [] - _filters_mutated() - -class _OptionError(Exception): - """Exception used by option processing helpers.""" - pass - -# Helper to process -W options passed via sys.warnoptions -def _processoptions(args): - for arg in args: - try: - _setoption(arg) - except _OptionError as msg: - print("Invalid -W option ignored:", msg, file=sys.stderr) - -# Helper for _processoptions() -def _setoption(arg): - parts = arg.split(':') - if len(parts) > 5: - raise _OptionError("too many fields (max 5): %r" % (arg,)) - while len(parts) < 5: - parts.append('') - action, message, category, module, lineno = [s.strip() - for s in parts] - action = _getaction(action) - category = _getcategory(category) - if message or module: - import re - if message: - message = re.escape(message) - if module: - module = re.escape(module) + r'\Z' - if lineno: - try: - lineno = int(lineno) - if lineno < 0: - raise ValueError - except (ValueError, OverflowError): - raise _OptionError("invalid lineno %r" % (lineno,)) from None - else: - lineno = 0 - filterwarnings(action, message, category, module, lineno) - -# Helper for _setoption() -def _getaction(action): - if not action: - return "default" - if action == "all": return "always" # Alias - for a in ('default', 'always', 'ignore', 'module', 'once', 'error'): - if a.startswith(action): - return a - raise _OptionError("invalid action: %r" % (action,)) - -# Helper for _setoption() -def _getcategory(category): - if not category: - return Warning - if '.' not in category: - import builtins as m - klass = category - else: - module, _, klass = category.rpartition('.') - try: - m = __import__(module, None, None, [klass]) - except ImportError: - raise _OptionError("invalid module name: %r" % (module,)) from None - try: - cat = getattr(m, klass) - except AttributeError: - raise _OptionError("unknown warning category: %r" % (category,)) from None - if not issubclass(cat, Warning): - raise _OptionError("invalid warning category: %r" % (category,)) - return cat - - -def _is_internal_frame(frame): - """Signal whether the frame is an internal CPython implementation detail.""" - filename = frame.f_code.co_filename - return 'importlib' in filename and '_bootstrap' in filename - - -def _next_external_frame(frame): - """Find the next frame that doesn't involve CPython internals.""" - frame = frame.f_back - while frame is not None and _is_internal_frame(frame): - frame = frame.f_back - return frame - - -# Code typically replaced by _warnings -def warn(message, category=None, stacklevel=1, source=None): - """Issue a warning, or maybe ignore it or raise an exception.""" - # Check if message is already a Warning object - if isinstance(message, Warning): - category = message.__class__ - # Check category argument - if category is None: - category = UserWarning - if not (isinstance(category, type) and issubclass(category, Warning)): - raise TypeError("category must be a Warning subclass, " - "not '{:s}'".format(type(category).__name__)) - # Get context information - try: - if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)): - # If frame is too small to care or if the warning originated in - # internal code, then do not try to hide any frames. - frame = sys._getframe(stacklevel) - else: - frame = sys._getframe(1) - # Look for one frame less since the above line starts us off. - for x in range(stacklevel-1): - frame = _next_external_frame(frame) - if frame is None: - raise ValueError - except ValueError: - globals = sys.__dict__ - lineno = 1 - else: - globals = frame.f_globals - lineno = frame.f_lineno - if '__name__' in globals: - module = globals['__name__'] - else: - module = "" - filename = globals.get('__file__') - if filename: - fnl = filename.lower() - if fnl.endswith(".pyc"): - filename = filename[:-1] - else: - if module == "__main__": - try: - filename = sys.argv[0] - except AttributeError: - # embedded interpreters don't have sys.argv, see bug #839151 - filename = '__main__' - if not filename: - filename = module - registry = globals.setdefault("__warningregistry__", {}) - warn_explicit(message, category, filename, lineno, module, registry, - globals, source) - -def warn_explicit(message, category, filename, lineno, - module=None, registry=None, module_globals=None, - source=None): - lineno = int(lineno) - if module is None: - module = filename or "" - if module[-3:].lower() == ".py": - module = module[:-3] # XXX What about leading pathname? - if registry is None: - registry = {} - if registry.get('version', 0) != _filters_version: - registry.clear() - registry['version'] = _filters_version - if isinstance(message, Warning): - text = str(message) - category = message.__class__ - else: - text = message - message = category(message) - key = (text, category, lineno) - # Quick test for common case - if registry.get(key): - return - # Search the filters - for item in filters: - action, msg, cat, mod, ln = item - if ((msg is None or msg.match(text)) and - issubclass(category, cat) and - (mod is None or mod.match(module)) and - (ln == 0 or lineno == ln)): - break - else: - action = defaultaction - # Early exit actions - if action == "ignore": - return - - # Prime the linecache for formatting, in case the - # "file" is actually in a zipfile or something. - import linecache - linecache.getlines(filename, module_globals) - - if action == "error": - raise message - # Other actions - if action == "once": - registry[key] = 1 - oncekey = (text, category) - if onceregistry.get(oncekey): - return - onceregistry[oncekey] = 1 - elif action == "always": - pass - elif action == "module": - registry[key] = 1 - altkey = (text, category, 0) - if registry.get(altkey): - return - registry[altkey] = 1 - elif action == "default": - registry[key] = 1 - else: - # Unrecognized actions are errors - raise RuntimeError( - "Unrecognized action (%r) in warnings.filters:\n %s" % - (action, item)) - # Print message and context - msg = WarningMessage(message, category, filename, lineno, source) - _showwarnmsg(msg) - - -class WarningMessage(object): - - _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", - "line", "source") - - def __init__(self, message, category, filename, lineno, file=None, - line=None, source=None): - self.message = message - self.category = category - self.filename = filename - self.lineno = lineno - self.file = file - self.line = line - self.source = source - self._category_name = category.__name__ if category else None - - def __str__(self): - return ("{message : %r, category : %r, filename : %r, lineno : %s, " - "line : %r}" % (self.message, self._category_name, - self.filename, self.lineno, self.line)) - - -class catch_warnings(object): - - """A context manager that copies and restores the warnings filter upon - exiting the context. - - The 'record' argument specifies whether warnings should be captured by a - custom implementation of warnings.showwarning() and be appended to a list - returned by the context manager. Otherwise None is returned by the context - manager. The objects appended to the list are arguments whose attributes - mirror the arguments to showwarning(). - - The 'module' argument is to specify an alternative module to the module - named 'warnings' and imported under that name. This argument is only useful - when testing the warnings module itself. - - """ - - def __init__(self, *, record=False, module=None): - """Specify whether to record warnings and if an alternative module - should be used other than sys.modules['warnings']. - - For compatibility with Python 3.0, please consider all arguments to be - keyword-only. - - """ - self._record = record - self._module = sys.modules['warnings'] if module is None else module - self._entered = False - - def __repr__(self): - args = [] - if self._record: - args.append("record=True") - if self._module is not sys.modules['warnings']: - args.append("module=%r" % self._module) - name = type(self).__name__ - return "%s(%s)" % (name, ", ".join(args)) - - def __enter__(self): - if self._entered: - raise RuntimeError("Cannot enter %r twice" % self) - self._entered = True - self._filters = self._module.filters - self._module.filters = self._filters[:] - self._module._filters_mutated() - self._showwarning = self._module.showwarning - self._showwarnmsg_impl = self._module._showwarnmsg_impl - if self._record: - log = [] - self._module._showwarnmsg_impl = log.append - # Reset showwarning() to the default implementation to make sure - # that _showwarnmsg() calls _showwarnmsg_impl() - self._module.showwarning = self._module._showwarning_orig - return log - else: - return None - - def __exit__(self, *exc_info): - if not self._entered: - raise RuntimeError("Cannot exit %r without entering first" % self) - self._module.filters = self._filters - self._module._filters_mutated() - self._module.showwarning = self._showwarning - self._module._showwarnmsg_impl = self._showwarnmsg_impl - - -# Private utility function called by _PyErr_WarnUnawaitedCoroutine -def _warn_unawaited_coroutine(coro): - msg_lines = [ - f"coroutine '{coro.__qualname__}' was never awaited\n" - ] - if coro.cr_origin is not None: - import linecache, traceback - def extract(): - for filename, lineno, funcname in reversed(coro.cr_origin): - line = linecache.getline(filename, lineno) - yield (filename, lineno, funcname, line) - msg_lines.append("Coroutine created at (most recent call last)\n") - msg_lines += traceback.format_list(list(extract())) - msg = "".join(msg_lines).rstrip("\n") - # Passing source= here means that if the user happens to have tracemalloc - # enabled and tracking where the coroutine was created, the warning will - # contain that traceback. This does mean that if they have *both* - # coroutine origin tracking *and* tracemalloc enabled, they'll get two - # partially-redundant tracebacks. If we wanted to be clever we could - # probably detect this case and avoid it, but for now we don't bother. - warn(msg, category=RuntimeWarning, stacklevel=2, source=coro) - - -# filters contains a sequence of filter 5-tuples -# The components of the 5-tuple are: -# - an action: error, ignore, always, default, module, or once -# - a compiled regex that must match the warning message -# - a class representing the warning category -# - a compiled regex that must match the module that is being warned -# - a line number for the line being warning, or 0 to mean any line -# If either if the compiled regexs are None, match anything. -try: - from _warnings import (filters, _defaultaction, _onceregistry, - warn, warn_explicit, _filters_mutated) - defaultaction = _defaultaction - onceregistry = _onceregistry - _warnings_defaults = True -except ImportError: - filters = [] - defaultaction = "default" - onceregistry = {} - - _filters_version = 1 - - def _filters_mutated(): - global _filters_version - _filters_version += 1 - - _warnings_defaults = False - - -# Module initialization -_processoptions(sys.warnoptions) -if not _warnings_defaults: - # Several warning categories are ignored by default in regular builds - if not hasattr(sys, 'gettotalrefcount'): - filterwarnings("default", category=DeprecationWarning, - module="__main__", append=1) - simplefilter("ignore", category=DeprecationWarning, append=1) - simplefilter("ignore", category=PendingDeprecationWarning, append=1) - simplefilter("ignore", category=ImportWarning, append=1) - simplefilter("ignore", category=ResourceWarning, append=1) - -del _warnings_defaults diff --git a/experiment/simulation/backend/venv/lib/python3.7/weakref.py b/experiment/simulation/backend/venv/lib/python3.7/weakref.py deleted file mode 100644 index 461c997..0000000 --- a/experiment/simulation/backend/venv/lib/python3.7/weakref.py +++ /dev/null @@ -1,656 +0,0 @@ -"""Weak reference support for Python. - -This module is an implementation of PEP 205: - -http://www.python.org/dev/peps/pep-0205/ -""" - -# Naming convention: Variables named "wr" are weak reference objects; -# they are called this instead of "ref" to avoid name collisions with -# the module-global ref() function imported from _weakref. - -from _weakref import ( - getweakrefcount, - getweakrefs, - ref, - proxy, - CallableProxyType, - ProxyType, - ReferenceType, - _remove_dead_weakref) - -from _weakrefset import WeakSet, _IterationGuard - -import _collections_abc # Import after _weakref to avoid circular import. -import sys -import itertools - -ProxyTypes = (ProxyType, CallableProxyType) - -__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", - "WeakKeyDictionary", "ReferenceType", "ProxyType", - "CallableProxyType", "ProxyTypes", "WeakValueDictionary", - "WeakSet", "WeakMethod", "finalize"] - - -class WeakMethod(ref): - """ - A custom `weakref.ref` subclass which simulates a weak reference to - a bound method, working around the lifetime problem of bound methods. - """ - - __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__" - - def __new__(cls, meth, callback=None): - try: - obj = meth.__self__ - func = meth.__func__ - except AttributeError: - raise TypeError("argument should be a bound method, not {}" - .format(type(meth))) from None - def _cb(arg): - # The self-weakref trick is needed to avoid creating a reference - # cycle. - self = self_wr() - if self._alive: - self._alive = False - if callback is not None: - callback(self) - self = ref.__new__(cls, obj, _cb) - self._func_ref = ref(func, _cb) - self._meth_type = type(meth) - self._alive = True - self_wr = ref(self) - return self - - def __call__(self): - obj = super().__call__() - func = self._func_ref() - if obj is None or func is None: - return None - return self._meth_type(func, obj) - - def __eq__(self, other): - if isinstance(other, WeakMethod): - if not self._alive or not other._alive: - return self is other - return ref.__eq__(self, other) and self._func_ref == other._func_ref - return False - - def __ne__(self, other): - if isinstance(other, WeakMethod): - if not self._alive or not other._alive: - return self is not other - return ref.__ne__(self, other) or self._func_ref != other._func_ref - return True - - __hash__ = ref.__hash__ - - -class WeakValueDictionary(_collections_abc.MutableMapping): - """Mapping class that references values weakly. - - Entries in the dictionary will be discarded when no strong - reference to the value exists anymore - """ - # We inherit the constructor without worrying about the input - # dictionary; since it uses our .update() method, we get the right - # checks (if the other dictionary is a WeakValueDictionary, - # objects are unwrapped on the way out, and we always wrap on the - # way in). - - def __init__(*args, **kw): - if not args: - raise TypeError("descriptor '__init__' of 'WeakValueDictionary' " - "object needs an argument") - self, *args = args - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref): - self = selfref() - if self is not None: - if self._iterating: - self._pending_removals.append(wr.key) - else: - # Atomic removal is necessary since this function - # can be called asynchronously by the GC - _atomic_removal(self.data, wr.key) - self._remove = remove - # A list of keys to be removed - self._pending_removals = [] - self._iterating = set() - self.data = {} - self.update(*args, **kw) - - def _commit_removals(self): - l = self._pending_removals - d = self.data - # We shouldn't encounter any KeyError, because this method should - # always be called *before* mutating the dict. - while l: - key = l.pop() - _remove_dead_weakref(d, key) - - def __getitem__(self, key): - if self._pending_removals: - self._commit_removals() - o = self.data[key]() - if o is None: - raise KeyError(key) - else: - return o - - def __delitem__(self, key): - if self._pending_removals: - self._commit_removals() - del self.data[key] - - def __len__(self): - if self._pending_removals: - self._commit_removals() - return len(self.data) - - def __contains__(self, key): - if self._pending_removals: - self._commit_removals() - try: - o = self.data[key]() - except KeyError: - return False - return o is not None - - def __repr__(self): - return "<%s at %#x>" % (self.__class__.__name__, id(self)) - - def __setitem__(self, key, value): - if self._pending_removals: - self._commit_removals() - self.data[key] = KeyedRef(value, self._remove, key) - - def copy(self): - if self._pending_removals: - self._commit_removals() - new = WeakValueDictionary() - with _IterationGuard(self): - for key, wr in self.data.items(): - o = wr() - if o is not None: - new[key] = o - return new - - __copy__ = copy - - def __deepcopy__(self, memo): - from copy import deepcopy - if self._pending_removals: - self._commit_removals() - new = self.__class__() - with _IterationGuard(self): - for key, wr in self.data.items(): - o = wr() - if o is not None: - new[deepcopy(key, memo)] = o - return new - - def get(self, key, default=None): - if self._pending_removals: - self._commit_removals() - try: - wr = self.data[key] - except KeyError: - return default - else: - o = wr() - if o is None: - # This should only happen - return default - else: - return o - - def items(self): - if self._pending_removals: - self._commit_removals() - with _IterationGuard(self): - for k, wr in self.data.items(): - v = wr() - if v is not None: - yield k, v - - def keys(self): - if self._pending_removals: - self._commit_removals() - with _IterationGuard(self): - for k, wr in self.data.items(): - if wr() is not None: - yield k - - __iter__ = keys - - def itervaluerefs(self): - """Return an iterator that yields the weak references to the values. - - The references are not guaranteed to be 'live' at the time - they are used, so the result of calling the references needs - to be checked before being used. This can be used to avoid - creating references that will cause the garbage collector to - keep the values around longer than needed. - - """ - if self._pending_removals: - self._commit_removals() - with _IterationGuard(self): - yield from self.data.values() - - def values(self): - if self._pending_removals: - self._commit_removals() - with _IterationGuard(self): - for wr in self.data.values(): - obj = wr() - if obj is not None: - yield obj - - def popitem(self): - if self._pending_removals: - self._commit_removals() - while True: - key, wr = self.data.popitem() - o = wr() - if o is not None: - return key, o - - def pop(self, key, *args): - if self._pending_removals: - self._commit_removals() - try: - o = self.data.pop(key)() - except KeyError: - o = None - if o is None: - if args: - return args[0] - else: - raise KeyError(key) - else: - return o - - def setdefault(self, key, default=None): - try: - o = self.data[key]() - except KeyError: - o = None - if o is None: - if self._pending_removals: - self._commit_removals() - self.data[key] = KeyedRef(default, self._remove, key) - return default - else: - return o - - def update(*args, **kwargs): - if not args: - raise TypeError("descriptor 'update' of 'WeakValueDictionary' " - "object needs an argument") - self, *args = args - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - dict = args[0] if args else None - if self._pending_removals: - self._commit_removals() - d = self.data - if dict is not None: - if not hasattr(dict, "items"): - dict = type({})(dict) - for key, o in dict.items(): - d[key] = KeyedRef(o, self._remove, key) - if len(kwargs): - self.update(kwargs) - - def valuerefs(self): - """Return a list of weak references to the values. - - The references are not guaranteed to be 'live' at the time - they are used, so the result of calling the references needs - to be checked before being used. This can be used to avoid - creating references that will cause the garbage collector to - keep the values around longer than needed. - - """ - if self._pending_removals: - self._commit_removals() - return list(self.data.values()) - - -class KeyedRef(ref): - """Specialized reference that includes a key corresponding to the value. - - This is used in the WeakValueDictionary to avoid having to create - a function object for each key stored in the mapping. A shared - callback object can use the 'key' attribute of a KeyedRef instead - of getting a reference to the key from an enclosing scope. - - """ - - __slots__ = "key", - - def __new__(type, ob, callback, key): - self = ref.__new__(type, ob, callback) - self.key = key - return self - - def __init__(self, ob, callback, key): - super().__init__(ob, callback) - - -class WeakKeyDictionary(_collections_abc.MutableMapping): - """ Mapping class that references keys weakly. - - Entries in the dictionary will be discarded when there is no - longer a strong reference to the key. This can be used to - associate additional data with an object owned by other parts of - an application without adding attributes to those objects. This - can be especially useful with objects that override attribute - accesses. - """ - - def __init__(self, dict=None): - self.data = {} - def remove(k, selfref=ref(self)): - self = selfref() - if self is not None: - if self._iterating: - self._pending_removals.append(k) - else: - del self.data[k] - self._remove = remove - # A list of dead weakrefs (keys to be removed) - self._pending_removals = [] - self._iterating = set() - self._dirty_len = False - if dict is not None: - self.update(dict) - - def _commit_removals(self): - # NOTE: We don't need to call this method before mutating the dict, - # because a dead weakref never compares equal to a live weakref, - # even if they happened to refer to equal objects. - # However, it means keys may already have been removed. - l = self._pending_removals - d = self.data - while l: - try: - del d[l.pop()] - except KeyError: - pass - - def _scrub_removals(self): - d = self.data - self._pending_removals = [k for k in self._pending_removals if k in d] - self._dirty_len = False - - def __delitem__(self, key): - self._dirty_len = True - del self.data[ref(key)] - - def __getitem__(self, key): - return self.data[ref(key)] - - def __len__(self): - if self._dirty_len and self._pending_removals: - # self._pending_removals may still contain keys which were - # explicitly removed, we have to scrub them (see issue #21173). - self._scrub_removals() - return len(self.data) - len(self._pending_removals) - - def __repr__(self): - return "<%s at %#x>" % (self.__class__.__name__, id(self)) - - def __setitem__(self, key, value): - self.data[ref(key, self._remove)] = value - - def copy(self): - new = WeakKeyDictionary() - with _IterationGuard(self): - for key, value in self.data.items(): - o = key() - if o is not None: - new[o] = value - return new - - __copy__ = copy - - def __deepcopy__(self, memo): - from copy import deepcopy - new = self.__class__() - with _IterationGuard(self): - for key, value in self.data.items(): - o = key() - if o is not None: - new[o] = deepcopy(value, memo) - return new - - def get(self, key, default=None): - return self.data.get(ref(key),default) - - def __contains__(self, key): - try: - wr = ref(key) - except TypeError: - return False - return wr in self.data - - def items(self): - with _IterationGuard(self): - for wr, value in self.data.items(): - key = wr() - if key is not None: - yield key, value - - def keys(self): - with _IterationGuard(self): - for wr in self.data: - obj = wr() - if obj is not None: - yield obj - - __iter__ = keys - - def values(self): - with _IterationGuard(self): - for wr, value in self.data.items(): - if wr() is not None: - yield value - - def keyrefs(self): - """Return a list of weak references to the keys. - - The references are not guaranteed to be 'live' at the time - they are used, so the result of calling the references needs - to be checked before being used. This can be used to avoid - creating references that will cause the garbage collector to - keep the keys around longer than needed. - - """ - return list(self.data) - - def popitem(self): - self._dirty_len = True - while True: - key, value = self.data.popitem() - o = key() - if o is not None: - return o, value - - def pop(self, key, *args): - self._dirty_len = True - return self.data.pop(ref(key), *args) - - def setdefault(self, key, default=None): - return self.data.setdefault(ref(key, self._remove),default) - - def update(self, dict=None, **kwargs): - d = self.data - if dict is not None: - if not hasattr(dict, "items"): - dict = type({})(dict) - for key, value in dict.items(): - d[ref(key, self._remove)] = value - if len(kwargs): - self.update(kwargs) - - -class finalize: - """Class for finalization of weakrefable objects - - finalize(obj, func, *args, **kwargs) returns a callable finalizer - object which will be called when obj is garbage collected. The - first time the finalizer is called it evaluates func(*arg, **kwargs) - and returns the result. After this the finalizer is dead, and - calling it just returns None. - - When the program exits any remaining finalizers for which the - atexit attribute is true will be run in reverse order of creation. - By default atexit is true. - """ - - # Finalizer objects don't have any state of their own. They are - # just used as keys to lookup _Info objects in the registry. This - # ensures that they cannot be part of a ref-cycle. - - __slots__ = () - _registry = {} - _shutdown = False - _index_iter = itertools.count() - _dirty = False - _registered_with_atexit = False - - class _Info: - __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index") - - def __init__(*args, **kwargs): - if len(args) >= 3: - self, obj, func, *args = args - elif not args: - raise TypeError("descriptor '__init__' of 'finalize' object " - "needs an argument") - else: - if 'func' not in kwargs: - raise TypeError('finalize expected at least 2 positional ' - 'arguments, got %d' % (len(args)-1)) - func = kwargs.pop('func') - if len(args) >= 2: - self, obj, *args = args - else: - if 'obj' not in kwargs: - raise TypeError('finalize expected at least 2 positional ' - 'arguments, got %d' % (len(args)-1)) - obj = kwargs.pop('obj') - self, *args = args - args = tuple(args) - - if not self._registered_with_atexit: - # We may register the exit function more than once because - # of a thread race, but that is harmless - import atexit - atexit.register(self._exitfunc) - finalize._registered_with_atexit = True - info = self._Info() - info.weakref = ref(obj, self) - info.func = func - info.args = args - info.kwargs = kwargs or None - info.atexit = True - info.index = next(self._index_iter) - self._registry[self] = info - finalize._dirty = True - - def __call__(self, _=None): - """If alive then mark as dead and return func(*args, **kwargs); - otherwise return None""" - info = self._registry.pop(self, None) - if info and not self._shutdown: - return info.func(*info.args, **(info.kwargs or {})) - - def detach(self): - """If alive then mark as dead and return (obj, func, args, kwargs); - otherwise return None""" - info = self._registry.get(self) - obj = info and info.weakref() - if obj is not None and self._registry.pop(self, None): - return (obj, info.func, info.args, info.kwargs or {}) - - def peek(self): - """If alive then return (obj, func, args, kwargs); - otherwise return None""" - info = self._registry.get(self) - obj = info and info.weakref() - if obj is not None: - return (obj, info.func, info.args, info.kwargs or {}) - - @property - def alive(self): - """Whether finalizer is alive""" - return self in self._registry - - @property - def atexit(self): - """Whether finalizer should be called at exit""" - info = self._registry.get(self) - return bool(info) and info.atexit - - @atexit.setter - def atexit(self, value): - info = self._registry.get(self) - if info: - info.atexit = bool(value) - - def __repr__(self): - info = self._registry.get(self) - obj = info and info.weakref() - if obj is None: - return '<%s object at %#x; dead>' % (type(self).__name__, id(self)) - else: - return '<%s object at %#x; for %r at %#x>' % \ - (type(self).__name__, id(self), type(obj).__name__, id(obj)) - - @classmethod - def _select_for_exit(cls): - # Return live finalizers marked for exit, oldest first - L = [(f,i) for (f,i) in cls._registry.items() if i.atexit] - L.sort(key=lambda item:item[1].index) - return [f for (f,i) in L] - - @classmethod - def _exitfunc(cls): - # At shutdown invoke finalizers for which atexit is true. - # This is called once all other non-daemonic threads have been - # joined. - reenable_gc = False - try: - if cls._registry: - import gc - if gc.isenabled(): - reenable_gc = True - gc.disable() - pending = None - while True: - if pending is None or finalize._dirty: - pending = cls._select_for_exit() - finalize._dirty = False - if not pending: - break - f = pending.pop() - try: - # gc is disabled, so (assuming no daemonic - # threads) the following is the only line in - # this function which might trigger creation - # of a new finalizer - f() - except Exception: - sys.excepthook(*sys.exc_info()) - assert f not in cls._registry - finally: - # prevent any more finalizers from executing during shutdown - finalize._shutdown = True - if reenable_gc: - gc.enable() diff --git a/experiment/simulation/exp.html b/experiment/simulation/exp.html index 103c013..6251b76 100755 --- a/experiment/simulation/exp.html +++ b/experiment/simulation/exp.html @@ -12,5 +12,5 @@ - + diff --git a/experiment/simulation/js/utils.js b/experiment/simulation/js/utils.js new file mode 100644 index 0000000..045dd88 --- /dev/null +++ b/experiment/simulation/js/utils.js @@ -0,0 +1,102 @@ +window.SERVER = + "svc-test.vlabs.ac.in/octave-ann"; + +function submitForm() { + const $form = $('form[name="myform"]'); + + let args = $form.serializeArray().reduce((prev, cur) => { + return { ...prev, [cur.name]: cur.value }; + }, {}); + + if (window.extraArgs) args = { ...args, ...window.extraArgs() }; + + $.ajax({ + url: SERVER + "/exp-" + window.EXP_NAME, + type: "POST", + headers: { + token: localStorage.getItem("token"), + }, + dataType: "json", + data: JSON.stringify(args), + contentType: "application/json", + success: function (data, status, xhr) { + if (status === "success") { + if (data.error) console.error(data.error); + else { + const $container = document.querySelector(".image-container"); + while ($container.firstElementChild) + $container.removeChild($container.firstElementChild); + const $result = $("#result"); + $result.html(""); + + if (data.images) { + for (let i = 1; i <= data.images.length; i++) { + const img = document.createElement("img"); + img.setAttribute("width", "600"); + img.classList.add("my-2"); + img.src = "data:image/png;base64," + data.images[i - 1]; + $container.appendChild(img); + } + } + + if (data.result) { + $result.html(data.result); + } + } + } + }, + error: function (err) { + console.log(err); + }, + }); +} + +function submit(e) { + submitForm(); + e.preventDefault(); +} + +/** + * @param elm {Element} + * @param list {Object} + */ +function appendOptions(elm, list) { + for (const [value, str] of Object.entries(list)) { + const option = document.createElement("option"); + option.innerText = str; + option.value = value; + elm.appendChild(option); + } + elm.firstElementChild.setAttribute("selected", "selected"); +} + +function onload() { + if (document.readyState === "complete") { + if (!localStorage.getItem("token")) { + $.get( + `${SERVER}/get_token`, + (success = function (data) { + localStorage.setItem("token", data); + }) + ); + } + if (window.appenditure) + for (const [elmName, value] of Object.entries(window.appenditure)) { + appendOptions(document.myform[elmName], value); + } + + if (window.otherSetters) { + for (const [key, value] of Object.entries(window.otherSetters)) { + document.myform[key].value = value; + } + } + + $('form[name="myform"]').submit(submit); + + submitForm(); + } else { + setTimeout(onload, 100); + } +} + +$(document).ready(onload); diff --git a/experiment/simulation/weightedmatching_det.html b/experiment/simulation/weightedmatching_det.html index a0d24e0..107b25e 100755 --- a/experiment/simulation/weightedmatching_det.html +++ b/experiment/simulation/weightedmatching_det.html @@ -50,7 +50,7 @@ - + diff --git a/experiment/simulation/weightedmatching_mean.html b/experiment/simulation/weightedmatching_mean.html index 7ce3cc8..9807547 100755 --- a/experiment/simulation/weightedmatching_mean.html +++ b/experiment/simulation/weightedmatching_mean.html @@ -42,7 +42,7 @@ - + +